.htaccess Variables Issue Unrecognized header format %

1k Views Asked by At

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?

1

There are 1 best solutions below

3
On BEST ANSWER

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.

Accessing the env var in the Header directive

Header 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?