Add warnings for dangerous content security policy settings autogenerated by Rails
Is your feature request related to a problem? Please describe.
I have recently noticed a problem with the default Content Security Policy generated by Rails, starting with Rails 6. The default generator adds the token https: to most rules, which allows the app to use JS, CSS, images, etc. from literally any server that serves that file over HTTPS.
This is probably a problem for the Rails team, but even after they fix it, I think it becomes a problem for Brakeman as well, because there will be a lot of apps out there that will still have https: in their rules.
I think the Rails team probably thought that the CSP rules are implemented as an 'AND' list, as in, 'only use sources in my allowlist' AND 'only allow resources fetched via HTTPS'. Unfortunately, it's actually an 'OR' list, where the https: part renders your allowlist useless.
I've had some trouble finding CSP documentation that explains this issue clearly, but I can show you these:
The MDN source-expression-list section says that these rules are an 'OR' list:
Resources of this type may be loaded if they match any of the given source expressions.
The w3.org source lists section explains that when you specify a scheme such as
https:, it:matches any resource having the specified scheme
I have also confirmed experimentally that a webpage with script_src: 'self' https:; in the CSP will run JavaScript that is served by either its own server or any other server, provided it is served over HTTPS. You may wish to try https://portswigger-labs.net/A.JS for this purpose (it contains a handy alert(1)).
Describe the solution you'd like
When the symbol :https appears uncommented anywhere in my Content Security Policy definition, at config/initializers/content_security_policy.rb, or within a config.content_security_policy block, I would like to see at least a medium if not high severity warning that my CSP is not providing the protections I intended.
Honestly, I can't think of any plausible reason to write https: in a CSP. It's nice to require encryption, but there's a better rule for this that doesn't invalidate the rest of my CSP: upgrade-insecure-requests.
Describe alternatives you've considered I've considered opening an issue in Rails to fix the default CSP, but I haven't done it yet. As described above, this will not fix the problem for a whole lot of people.
EDIT: Discussion linked here: https://discuss.rubyonrails.org/t/improper-defaults-in-generated-content-security-policy/91534
Additional context For reference, here's the CSP that Rails generates by default:
Rails.application.configure do
config.content_security_policy do |policy|
policy.default_src :self, :https
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data
policy.object_src :none
policy.script_src :self, :https
policy.style_src :self, :https
# Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint"
end
...
end... and here's what it turns into in your headers:
content-security-policy
default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src 'self' https:; style-src 'self' https:;Note all the https:'s rendering the 'self' keyword useless.
Source: presidentbeef/brakeman