I use ansible (which uses jinja2) to manage nginx. My nginx config file has a very long line which is hard to maintain:
add_header Content-Security-Policy "default-src 'self' http: https: https://*.foo.com: https://*.bar.com: https://*.baz.com: https://*.qux.com: https://*.spam.com: https://*.ham.com: https://*.eggs.com: wss://*.foo.com: object-src 'none'" always;
Since the config file is a jinja2 template, I want to rewrite that single line as multiple lines (for ease of maintenance), but for it to be transformed to one line as above.
How do I do that? In other words something like this (doesn't work of course):
add_header Content-Security-Policy {%
"default-src 'self'
http:
https:
https://*.foo.com:
https://*.bar.com:
https://*.baz.com:
https://*.qux.com:
https://*.spam.com:
https://*.ham.com:
https://*.eggs.com:
wss://*.foo.com:
object-src 'none'"
always;%}
...which when transformed, will give me the one liner shown above?
A possible solution: put your needed values in a list and join them with spaces:
{%- set my_values=[
"default-src 'self'",
"http:",
"https:",
"https://*.foo.com:",
"https://*.bar.com:",
"https://*.baz.com:",
"https://*.qux.com:",
"https://*.spam.com:",
"https://*.ham.com:",
"https://*.eggs.com:",
"wss://*.foo.com:",
"object-src 'none'",
"always",
]-%}
add_header Content-Security-Policy "{{ my_values | join(' ') }}";
Cherry on the cake: pass this list directly to your template from a var you declare in your inventory/playbook.
Related
I am trying to add Content-Security-Policy to my Blazor Server website. I do this by adding this to Startup.cs, in Configure method:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add(
"Content-Security-Policy",
"base-uri 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g=='; " +
"block-all-mixed-content;" +
"default-src 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g=='" +
"img-src data: https:; " +
"script-src 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g=='; " +
"style-src 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g==';" +
"font-src 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g==';" +
"upgrade-insecure-requests;" +
"connect-src 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g==';");
await next(); });
But the problem I am facing is that some libraries I use (which I include locally in the project) throws errors. For example, fontawesome/all.js throws an error saying
"all.js:2626 Refused to apply inline style because it violates the
following Content Security Policy directive: "style-src 'self'
'nonce-rAnd0m'". Either the 'unsafe-inline' keyword, a hash
('sha256-ixVUGs3ai0rMA0pgIVBN0KVlYbQip7/5SGmnUwJPNqE='), or a nonce
('nonce-...') is required to enable inline execution."
I added a nonce to the file links, in _Host.cshtml like this:
<link href="~/lib/font-awesome/css/fontawesome.css" rel="stylesheet" nonce="8IBTHwOdqNKAWeKl7plt8g==" />
<script src="~/lib/font-awesome/js/all.js" nonce="8IBTHwOdqNKAWeKl7plt8g=="></script>
but this still causes an error. How can I continue to use these libraries, without relaxing the security policy?
EDIT:
I noticed that, when the page renders, the links to my libraries get the nonce stripped out, like this:
<script src="/lib/font-awesome/js/all.js" nonce></script>
EDIT
I also found that if I remove "default-src 'self' 'nonce-8IBTHwOdqNKAWeKl7plt8g=='" I no longer get any errors. But, the nonce seems to make no difference. I can have nonces that don't match the style/js links and they all still work, so I am not sure what the point of the nonce is?
Not sure why the docs are vague on this, but I'm trying to set security headers which is fine except when I want to allow certain domains, just not working. Getting errors in console.
"headers": [
{
"key": "Content-Security-Policy",
"value": "default-src 'self' *.myDomain.com; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://*.stripe.com *.stripe.com https://*.split.io *.split.io; connect-src vitals.vercel-insights.com;"
},
Basically, getting security errors for all the split.io items (auth.split..., sdk.split....), and for the vercel insights...
Must be a fomatting issue.....
We have a dotnet core application hosted in IIS, with url of format application1.domain.com. We have added
options.AddPolicy("AllowAllOrigins",
builder =>
{
builder
.WithOrigins(webURL,"https://*.domain.com")
.AllowAnyHeader()
.AllowAnyMethod()
.WithExposedHeaders("Content-Disposition");
});
Also have this,
app.Use(async (context, next) =>
{context.Response.Headers.Add("Content-Security-Policy", "default-src 'self' 'unsafe-eval' 'unsafe-inline' *.domain.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' *.domain.com data:; connect-src 'self' *.domain.com; form-action 'self' ;");}
We are getting this below error in chrome, when https://application2.domain.com/ application try to load https://application1.domain.com/angular.js inside their html file.
Refused to load the script 'https://{application}.domain.com/angular.js' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval' www.google-analytics.com ajax.googeapis.com *.api.splkmobile.com". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
Any other settings need to be done from https://application2.domain.com end?
You show the CSP having script-src 'self' 'unsafe-inline' 'unsafe-eval'; but violation occurs at script-src 'self' 'unsafe-inline' 'unsafe-eval' www.google-analytics.com ajax.googeapis.com *.api.splkmobile.com.
This means other CSP is published somewhere, and CSP you shown is not published.
You have to find where really CSP header is issued and add https://application2.domain.com into it.
I have an nginx conf which I pair with various applications to act as a reverse proxy.
I would like to enforce some specific response headers but allow the upstream service the freedom to override them.
If the inheritance rules for nginx were different, I would do something like
if ($sent_http_x_content_length = '') {
add_header X-Content-Length "nosniff" always;
}
if ($sent_http_content_type = '') {
add_header Content-Type "text/html" always;
}
But of course, since it's inside the if, the previous if blocks are overwritten.
What is a good workaround that doesn't involve installing the headers-more module?
Ultimately I went with the nginx-plus officially sanctioned more_set_headers community module.
map $sent_http_x_powered_by $resp_x_powered_by {
default $sent_http_x_powered_by;
"" "x powered by is empty";
}
map $sent_http_x_foo $resp_x_foo {
default "x foo by is set";
"" "x foo by is empty";
}
server {
add_header "SomeHeader" "SomeValue";
...
location / {
more_set_headers "X-Powered-By: $resp_x_powered_by";
more_set_headers X-Foo $resp_x_foo;
}
How this works:
more_set_headers will overwrite the headers that you specify with the value provided, e.g. $resp_x_powered_by
The map block will evaluate $resp_x_powered_by by looking at the string in $sent_http_x_powered_by.
If the string is "" then we use the default value of "x powered by is empty". Otherwise, we use the value from the upstream server.
Why I did this:
Initially I tried to use add_headers with map as Raul suggested, but the issue lies in header duplication. If the header is set, then add_header will simply add another line to define the header again. A common workaround is to use proxy_hide_header but that blanks out the value so when we hit the map block, it will always evaluate to "".
As you can see, there is an add_header block outside of the location block which would be overridden by scope inheritance. There are ways to get around it but more_set_headers solves that issue.
I have the following in my nginx.conf
add_header Content-Security-Policy
"default-src 'self';
img-src 'self' 'unsafe-inline' 'unsafe-eval' data: *.printfriendly.com *.w.org *.gravatar.com *.vimeocdn.com;
script-src 'self' 'unsafe-inline' 'unsafe-eval' *.w.org *.gravatar.com *.googleapis.com *.jsdelivr.net *.printfriendly.com *.kxcdn.com *.vimeocdn.com *.hs-analytics.net *.securitymetrics.com *.google-analytics.com;
style-src 'self' 'unsafe-inline' *.googleapis.com *.bootstrapcdn.com *.gstatic.com *.vimeocdn.com;
font-src 'self' data: *.googleapis.com *.bootstrapcdn.com *.gstatic.com *.googleapis.com;
frame-src 'self' *.vimeocdn.com *.vimeo.com;
object-src 'self'";
(i had to multi-line it to make it legible...)
However, in my site I am still getting this error:
Content Security Policy: The page’s settings blocked the loading of a resource at http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css (“style-src”).
Any ideas why this may be happenning, when it is whitelisted above?
As #tarun-lalwani mentioned, any add_header directive in another blocks can matter. More precisely, if add_header (for any header) is used in a descendant block, this Content-Security-Policy will be discarded in such descendant block.
An excerpt from the documentation:
These directives are inherited from the previous level if and only if
there are no add_header directives defined on the current level.
To avoid code copy (DRY) the variables or include directive can be used (or generating nginx config in extensive case).
Just in case, in a real config a multi-line header value should not be used. Check your server response via curl -I https://example.com/path. For better readability in the config the variables can be used.
Example:
set $CSP_image "img-src 'self' 'unsafe-inline' 'unsafe-eval' data: *.printfriendly.com *.w.org *.gravatar.com *.vimeocdn.com; ";
set $CSP_script "script-src 'self' 'unsafe-inline' 'unsafe-eval' *.w.org *.gravatar.com *.googleapis.com *.jsdelivr.net *.printfriendly.com *.kxcdn.com *.vimeocdn.com *.hs-analytics.net *.securitymetrics.com *.google-analytics.com; ";
set $CSP_style "style-src 'self' 'unsafe-inline' *.googleapis.com *.bootstrapcdn.com *.gstatic.com *.vimeocdn.com; ";
set $CSP_font "font-src 'self' data: *.googleapis.com *.bootstrapcdn.com *.gstatic.com *.googleapis.com; ";
set $CSP_frame "frame-src 'self' *.vimeocdn.com *.vimeo.com; ";
set $CSP_object "object-src 'self' ; ";
set $CSP "default-src 'self' ; ${CSP_image} ${CSP_script} ${CSP_style} ${CSP_font} ${CSP_frame} ${CSP_object}";
add_header Content-Security-Policy $CSP;