From bad7d2666e053cb9bb1381e3d4f6fdf6107cf3f8 Mon Sep 17 00:00:00 2001 From: mutantmonkey Date: Tue, 8 Jan 2019 19:56:09 +0000 Subject: [PATCH] Switch to Referrer-Policy header (#149) Use of the Content-Security-Policy header to specify a referrer policy was deprecated in favor of a [new header](https://github.com/w3c/webappsec-referrer-policy/commit/fc55d917bee0d5636f52a19a5aefa65f8995c766). This change changes the existing referrer policy directives to use this header and adds corresponding config options/command line flags. --- README.md | 6 ++++-- csp.go | 11 +++++++++-- csp_test.go | 11 +++++++---- fileserve.go | 1 + server.go | 17 +++++++++++++---- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7fa6b68..e1a5c8a 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,10 @@ allowhotlink = true - ```-maxsize 4294967296``` -- maximum upload file size in bytes (default 4GB) - ```-maxexpiry 86400``` -- maximum expiration time in seconds (default is 0, which is no expiry) - ```-allowhotlink``` -- Allow file hotlinking -- ```-contentsecuritypolicy "..."``` -- Content-Security-Policy header for pages (default is "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; referrer origin;") -- ```-filecontentsecuritypolicy "..."``` -- Content-Security-Policy header for files (default is "default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; referrer origin;") +- ```-contentsecuritypolicy "..."``` -- Content-Security-Policy header for pages (default is "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-ancestors 'self';") +- ```-filecontentsecuritypolicy "..."``` -- Content-Security-Policy header for files (default is "default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self';") +- ```-refererpolicy "..."``` -- Referrer-Policy header for pages (default is "same-origin") +- ```-filereferrerpolicy "..."``` -- Referrer-Policy header for files (default is "same-origin") - ```-xframeoptions "..." ``` -- X-Frame-Options header (default is "SAMEORIGIN") - ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...) - ```-nologs``` -- (optionally) disable request logs in stdout diff --git a/csp.go b/csp.go index 098e271..34b73b4 100644 --- a/csp.go +++ b/csp.go @@ -6,6 +6,7 @@ import ( const ( cspHeader = "Content-Security-Policy" + rpHeader = "Referrer-Policy" frameOptionsHeader = "X-Frame-Options" ) @@ -15,8 +16,9 @@ type csp struct { } type CSPOptions struct { - policy string - frame string + policy string + referrerPolicy string + frame string } func (c csp) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -25,6 +27,11 @@ func (c csp) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Add(cspHeader, c.opts.policy) } + // only add a Referrer Policy if one is not already set + if existing := w.Header().Get(rpHeader); existing == "" { + w.Header().Add(rpHeader, c.opts.referrerPolicy) + } + w.Header().Set(frameOptionsHeader, c.opts.frame) c.h.ServeHTTP(w, r) diff --git a/csp_test.go b/csp_test.go index 190c65d..3d1d499 100644 --- a/csp_test.go +++ b/csp_test.go @@ -12,6 +12,7 @@ import ( var testCSPHeaders = map[string]string{ "Content-Security-Policy": "default-src 'none'; style-src 'self';", + "Referrer-Policy": "strict-origin-when-cross-origin", "X-Frame-Options": "SAMEORIGIN", } @@ -22,8 +23,9 @@ func TestContentSecurityPolicy(t *testing.T) { Config.maxSize = 1024 * 1024 * 1024 Config.noLogs = true Config.siteName = "linx" - Config.contentSecurityPolicy = "default-src 'none'; style-src 'self';" - Config.xFrameOptions = "SAMEORIGIN" + Config.contentSecurityPolicy = testCSPHeaders["Content-Security-Policy"] + Config.referrerPolicy = testCSPHeaders["Referrer-Policy"] + Config.xFrameOptions = testCSPHeaders["X-Frame-Options"] mux := setup() w := httptest.NewRecorder() @@ -34,8 +36,9 @@ func TestContentSecurityPolicy(t *testing.T) { } goji.Use(ContentSecurityPolicy(CSPOptions{ - policy: testCSPHeaders["Content-Security-Policy"], - frame: testCSPHeaders["X-Frame-Options"], + policy: testCSPHeaders["Content-Security-Policy"], + referrerPolicy: testCSPHeaders["Referrer-Policy"], + frame: testCSPHeaders["X-Frame-Options"], })) mux.ServeHTTP(w, req) diff --git a/fileserve.go b/fileserve.go index f7f87a6..951bea2 100644 --- a/fileserve.go +++ b/fileserve.go @@ -32,6 +32,7 @@ func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) { } w.Header().Set("Content-Security-Policy", Config.fileContentSecurityPolicy) + w.Header().Set("Referrer-Policy", Config.fileReferrerPolicy) fileBackend.ServeFile(fileName, w, r) } diff --git a/server.go b/server.go index ba0efb8..5280503 100644 --- a/server.go +++ b/server.go @@ -46,6 +46,8 @@ var Config struct { keyFile string contentSecurityPolicy string fileContentSecurityPolicy string + referrerPolicy string + fileReferrerPolicy string xFrameOptions string maxSize int64 maxExpiry uint64 @@ -88,8 +90,9 @@ func setup() *web.Mux { mux.Use(middleware.Recoverer) mux.Use(middleware.AutomaticOptions) mux.Use(ContentSecurityPolicy(CSPOptions{ - policy: Config.contentSecurityPolicy, - frame: Config.xFrameOptions, + policy: Config.contentSecurityPolicy, + referrerPolicy: Config.referrerPolicy, + frame: Config.xFrameOptions, })) mux.Use(AddHeaders(Config.addHeaders)) @@ -233,11 +236,17 @@ func main() { flag.StringVar(&Config.remoteAuthFile, "remoteauthfile", "", "path to a file containing newline-separated scrypted auth keys for remote uploads") flag.StringVar(&Config.contentSecurityPolicy, "contentsecuritypolicy", - "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; referrer origin;", + "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-ancestors 'self';", "value of default Content-Security-Policy header") flag.StringVar(&Config.fileContentSecurityPolicy, "filecontentsecuritypolicy", - "default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; referrer origin;", + "default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self';", "value of Content-Security-Policy header for file access") + flag.StringVar(&Config.referrerPolicy, "referrerpolicy", + "same-origin", + "value of default Referrer-Policy header") + flag.StringVar(&Config.fileReferrerPolicy, "filereferrerpolicy", + "same-origin", + "value of Referrer-Policy header for file access") flag.StringVar(&Config.xFrameOptions, "xframeoptions", "SAMEORIGIN", "value of X-Frame-Options header") flag.Var(&Config.addHeaders, "addheader",