I am building out a sort of Content Security Policy generator for one of my sites. I am stumped by one particular section of the .htaccess portion of it
The generated .htaccess is:
# Media Sources
SetEnv CSP_Media "media-src 'self' ;"
# Default Sources
SetEnv CSP_Default "default-src 'self' kevinpirnie.com ;"
# Add the CSP Headers
SetEnv CSP "%{ENV:CSP_Default} %{ENV:CSP_Media}"
Header always set Content-Security-Policy %{ENV:CSP}
Header always set X-Content-Security-Policy %{ENV:CSP}
When I leave the quotes off the SetEnv CSP
line, I get a different error: SetEnv takes 1-2 arguments
which makes sense... but with the quotes around them, I am getting the Unrecognized header format %
error
Any ideas what I can do to utilize variables for this, or how to fix the header format
issue?
There are a few issues here...
SetEnv CSP "%{ENV:CSP_Default} %{ENV:CSP_Media}"
This actually sets the CSP
environment variable to the literal value %{ENV:CSP_Default} %{ENV:CSP_Media}
- the CSP_Default
and CSP_Media
env vars are not expanded. AFAIK there is no way to reference env vars in the value argument of the SetEnv
directive.
You can use mod_rewrite (or SetEnvIfExpr
- see below) instead to create this CSP
env var that is the concatenation of two existing env vars, separated by a space.
HOWEVER, SetEnv
(mod_env) is processed too late in the request for mod_rewrite (which is processed very early) to be able to read these env vars. So you will need to use SetEnvIf
(mod_setenvif) instead (or use mod_rewrite as well to set the initial env vars).
For example:
RewriteEngine On
# Media Sources
SetEnvIf ^ ^ "CSP_Media=media-src 'self' ;"
# Default Sources
SetEnvIf ^ ^ "CSP_Default=default-src 'self' kevinpirnie.com ;"
# Add the CSP Headers
RewriteRule ^ - "[E=CSP:%{ENV:CSP_Media} %{ENV:CSP_Default}]"
Note the strategically placed double-quotes because the value argument contains spaces.
SetEnvIf
- the entire name=value
pair in the SetEnvIf
directive must be surrounded in double quotes (not the value).
RewriteRule
- the entire flags argument needs to be surrounded in double quotes (not the value).
UPDATE: You can avoid the use of mod_rewrite in the above and use the SetEnvIfExpr
directive instead to concatenate the env vars using an Apache expression (Apache 2.4).
For example:
# Add the CSP Headers
SetEnvIfExpr "reqenv('CSP_Media').' '.reqenv('CSP_Default') =~ /(.*)/" CSP=$1
The dots (.
) on the LHS of the expression are string concatenation operators (much like PHP). They do not appear as part of the string captured by the regex (RHS) and used as the concatenated value in the $1
backreference.
Header
directiveHeader always set Content-Security-Policy %{ENV:CSP} Header always set X-Content-Security-Policy %{ENV:CSP}
mod_headers uses a different syntax to access the value of env vars, hence the "Unrecognized header format %" error. You need to use %{var}e
instead.
For example:
Header always set Content-Security-Policy %{CSP}e
Header always set X-Content-Security-Policy %{CSP}e
Alternatively, you can avoid mod_rewrite and mod_setenvif by not creating your intermediate CSP
env var and just combine them in the Header
directive.
For example:
# Media Sources
SetEnv CSP_Media "media-src 'self' ;"
# Default Sources
SetEnv CSP_Default "default-src 'self' kevinpirnie.com ;"
# Add the CSP Headers
Header always set Content-Security-Policy "%{CSP_Media}e %{CSP_Default}e"
Header always set X-Content-Security-Policy "%{CSP_Media}e %{CSP_Default}e"
Because of the space, the value argument needs to be surrounded in double quotes.
I am building out a sort of Content Security Policy generator for one of my sites.
Although, if this code is "auto-generated"(?) then why not just generate the complete Header
in a single step?