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](fc55d917be).
This change changes the existing referrer policy directives to use this
header and adds corresponding config options/command line flags.
This commit is contained in:
mutantmonkey 2019-01-08 19:56:09 +00:00 committed by Andrei Marcu
parent 19a95e36a6
commit bad7d2666e
5 changed files with 34 additions and 12 deletions

View File

@ -47,8 +47,10 @@ allowhotlink = true
- ```-maxsize 4294967296``` -- maximum upload file size in bytes (default 4GB) - ```-maxsize 4294967296``` -- maximum upload file size in bytes (default 4GB)
- ```-maxexpiry 86400``` -- maximum expiration time in seconds (default is 0, which is no expiry) - ```-maxexpiry 86400``` -- maximum expiration time in seconds (default is 0, which is no expiry)
- ```-allowhotlink``` -- Allow file hotlinking - ```-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;") - ```-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'; 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';")
- ```-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") - ```-xframeoptions "..." ``` -- X-Frame-Options header (default is "SAMEORIGIN")
- ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...) - ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...)
- ```-nologs``` -- (optionally) disable request logs in stdout - ```-nologs``` -- (optionally) disable request logs in stdout

11
csp.go
View File

@ -6,6 +6,7 @@ import (
const ( const (
cspHeader = "Content-Security-Policy" cspHeader = "Content-Security-Policy"
rpHeader = "Referrer-Policy"
frameOptionsHeader = "X-Frame-Options" frameOptionsHeader = "X-Frame-Options"
) )
@ -15,8 +16,9 @@ type csp struct {
} }
type CSPOptions struct { type CSPOptions struct {
policy string policy string
frame string referrerPolicy string
frame string
} }
func (c csp) ServeHTTP(w http.ResponseWriter, r *http.Request) { 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) 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) w.Header().Set(frameOptionsHeader, c.opts.frame)
c.h.ServeHTTP(w, r) c.h.ServeHTTP(w, r)

View File

@ -12,6 +12,7 @@ import (
var testCSPHeaders = map[string]string{ var testCSPHeaders = map[string]string{
"Content-Security-Policy": "default-src 'none'; style-src 'self';", "Content-Security-Policy": "default-src 'none'; style-src 'self';",
"Referrer-Policy": "strict-origin-when-cross-origin",
"X-Frame-Options": "SAMEORIGIN", "X-Frame-Options": "SAMEORIGIN",
} }
@ -22,8 +23,9 @@ func TestContentSecurityPolicy(t *testing.T) {
Config.maxSize = 1024 * 1024 * 1024 Config.maxSize = 1024 * 1024 * 1024
Config.noLogs = true Config.noLogs = true
Config.siteName = "linx" Config.siteName = "linx"
Config.contentSecurityPolicy = "default-src 'none'; style-src 'self';" Config.contentSecurityPolicy = testCSPHeaders["Content-Security-Policy"]
Config.xFrameOptions = "SAMEORIGIN" Config.referrerPolicy = testCSPHeaders["Referrer-Policy"]
Config.xFrameOptions = testCSPHeaders["X-Frame-Options"]
mux := setup() mux := setup()
w := httptest.NewRecorder() w := httptest.NewRecorder()
@ -34,8 +36,9 @@ func TestContentSecurityPolicy(t *testing.T) {
} }
goji.Use(ContentSecurityPolicy(CSPOptions{ goji.Use(ContentSecurityPolicy(CSPOptions{
policy: testCSPHeaders["Content-Security-Policy"], policy: testCSPHeaders["Content-Security-Policy"],
frame: testCSPHeaders["X-Frame-Options"], referrerPolicy: testCSPHeaders["Referrer-Policy"],
frame: testCSPHeaders["X-Frame-Options"],
})) }))
mux.ServeHTTP(w, req) mux.ServeHTTP(w, req)

View File

@ -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("Content-Security-Policy", Config.fileContentSecurityPolicy)
w.Header().Set("Referrer-Policy", Config.fileReferrerPolicy)
fileBackend.ServeFile(fileName, w, r) fileBackend.ServeFile(fileName, w, r)
} }

View File

@ -46,6 +46,8 @@ var Config struct {
keyFile string keyFile string
contentSecurityPolicy string contentSecurityPolicy string
fileContentSecurityPolicy string fileContentSecurityPolicy string
referrerPolicy string
fileReferrerPolicy string
xFrameOptions string xFrameOptions string
maxSize int64 maxSize int64
maxExpiry uint64 maxExpiry uint64
@ -88,8 +90,9 @@ func setup() *web.Mux {
mux.Use(middleware.Recoverer) mux.Use(middleware.Recoverer)
mux.Use(middleware.AutomaticOptions) mux.Use(middleware.AutomaticOptions)
mux.Use(ContentSecurityPolicy(CSPOptions{ mux.Use(ContentSecurityPolicy(CSPOptions{
policy: Config.contentSecurityPolicy, policy: Config.contentSecurityPolicy,
frame: Config.xFrameOptions, referrerPolicy: Config.referrerPolicy,
frame: Config.xFrameOptions,
})) }))
mux.Use(AddHeaders(Config.addHeaders)) mux.Use(AddHeaders(Config.addHeaders))
@ -233,11 +236,17 @@ func main() {
flag.StringVar(&Config.remoteAuthFile, "remoteauthfile", "", flag.StringVar(&Config.remoteAuthFile, "remoteauthfile", "",
"path to a file containing newline-separated scrypted auth keys for remote uploads") "path to a file containing newline-separated scrypted auth keys for remote uploads")
flag.StringVar(&Config.contentSecurityPolicy, "contentsecuritypolicy", 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") "value of default Content-Security-Policy header")
flag.StringVar(&Config.fileContentSecurityPolicy, "filecontentsecuritypolicy", 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") "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", flag.StringVar(&Config.xFrameOptions, "xframeoptions", "SAMEORIGIN",
"value of X-Frame-Options header") "value of X-Frame-Options header")
flag.Var(&Config.addHeaders, "addheader", flag.Var(&Config.addHeaders, "addheader",