Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nonced tag helpers including nonce directive in csp has potential to break applications #470

Open
pcasaretto opened this issue Mar 23, 2021 · 17 comments

Comments

@pcasaretto
Copy link

pcasaretto commented Mar 23, 2021

Bugs

Nonced tag helpers including nonce directive in csp has potential to break applications

Problem

Given an application with inline script tags, and a CSP that allows them with 'unsafe-inline', using nonced_javascript_tag will cause a nonce directive to appear in the CSP header. Modern browsers will then ignore the 'unsafe-inline' directive and all other script tags without a nonce will cease to be executed.

@pcasaretto
Copy link
Author

Just to be clear, I'm more than willing to submit a PR once we decided this is a problem worth solving on this gem.

@oreoshake
Copy link
Contributor

However, as soon as we use nonced_javascript_tag on a page, the nonce directive appears on the enforcing CSP header

This sounds like more of a bug than a feature request. I would expect it to work without having to declare it. Would you only want to apply it to the report-only configuration?

Are you using both csp and csp-report-only? I could see how that use case wasn't considered/tested.

@pcasaretto
Copy link
Author

Are you using both csp and csp-report-only?

That is the case, yes. As we fix issues we find in the incoming reports, we migrate the directives from csp-report-only to csp.

@oreoshake
Copy link
Contributor

I'm more than willing to submit a PR once we decided this is a problem worth solving on this gem.

I'm more than willing to merge and release that 👍

@pcasaretto
Copy link
Author

pcasaretto commented Mar 23, 2021

A teammate just pointed out to me that this behavior was the cause of a recent outage.
The rollbar gem recently added CSP compatibility. When we deployed that update, it included the nonce directive in the csp header breaking all other inline scripts.

What do you think is the right way forward?
From my limited point of view, I'd like to remove the "magic" from the helper tags and make it their only responsibility to output tags with the proper attribute and value. Of course this means adding functionality for declaring the use of the nonce directive on the configuration setup.

@pcasaretto
Copy link
Author

With your approval, I'd like to edit the issue to make it clear that the current behavior of using nonced tags with a config using 'unsafe-inline' is a bug.

@oreoshake
Copy link
Contributor

With your approval, I'd like to edit the issue to make it clear that the current behavior of using nonced tags with a config using 'unsafe-inline' is a bug.

👍

@pcasaretto pcasaretto changed the title Support nonced tags while using report only mode nonced tag helpers including nonce directive in csp has potential to break applications Mar 23, 2021
@pcasaretto
Copy link
Author

Done! Any suggestions regarding how to proceed?

@oreoshake
Copy link
Contributor

Done! Any suggestions regarding how to proceed?

I would hope it would be as straightforward as pattern matching off of the existing code. I think the original proposal was to add a new helper/config option to the existing helper? It seems like you might want that functionality if you only want nonces in your report-only header.

But the simplest place to start would be a test that shows that by default, the nonce is added to both headers. Then, add the config option to specify which header the nonce should go in.

@pcasaretto
Copy link
Author

add the config option to specify which header the nonce should go in

Just to be clear: by that you mean an additional config option that would be fed into SecureHeaders::Configuration.default do |config| ?
What should the default behavior be? Preserve the current behavior? In that case, should we plan for a breaking change that fixes this problem?

@oreoshake
Copy link
Contributor

Just to be clear: by that you mean an additional config option that would be fed into SecureHeaders::Configuration.default do |config| ?

🤔 I'm not sure actually. My initial thought was to add it to nonced_javascript_tag but that could be a lot of work for not a lot of value. Maybe a global config would be better.

What should the default behavior be? Preserve the current behavior?

The default behavior.

In that case, should we plan for a breaking change that fixes this problem?

What breaking change would be introduced by preserving the current behavior?

@pcasaretto
Copy link
Author

What breaking change would be introduced by preserving the current behavior?

Allow me rephrase the question. Given that

  • the current behavior is dangerous, and might break apps that inadvertedly use nonced_javascript_tag
  • we also don't want to change the current behavior without signaling this using semantic versioning
    Is it in your plans to prepare a new major version that does not include this bug?

@oreoshake
Copy link
Contributor

It still seems like we might not be on the same page.

the current behavior is dangerous, and might break apps that inadvertedly use nonced_javascript_tag

Can you elaborate on "dangerous?" It seems to me the current functionality isn't desirable for your use case but it behaves consistently and hasn't been an issue until now. You're reasonably surprised that this functionality isn't supported, but I can't think of a scenario where something becomes inadvertently broken today.

we also don't want to change the current behavior without signaling this using semantic versioning. Is it in your plans to prepare a new major version that does not include this bug?

I'm not planning to because I don't think we should change the default behavior. The current behavior doesn't address your use case but we can work around that without affecting every other installation. If I could rewrite history, I wish this would have been addressed. But forcing everyone to update their configs, even if it's easy, for this edge case, doesn't seem like the best experience for those using this gem nor will it provide any value to almost everyone.

@pcasaretto
Copy link
Author

The following scenario hapenned in production with us:

  • we have a pretty sizeable Rails app with a lot Javascript. Several instances of javascript_tag and plain <script> tags inside views.
  • Rollbar calls content_security_policy_script_nonce to include a nonce on the script tag it generates
  • SecureHeaders adds the nonce directive the enforcing CSP header
  • the browser refuses all other instances of inline JS because these do not contain the nonce, which breaks most of our app

It caught us offguard because of the recent update I mentioned earlier in the thread.
While in this case, it was another gem that caused the issue, it's easy to imagine a scenario where the developers themselves add a nonced_javascript_tag to a page without replacing all occurrences of inline scripts.

@oreoshake
Copy link
Contributor

I can appreciate that and I hope that the surprise was discovered during pre-production testing but again, I'm not seeing a good enough justification for affecting anyone who depends on the current behavior. Is it surprising and unfortunate, yes, but it's easily discoverable.

@pcasaretto
Copy link
Author

Alas, it was not.
Moving forward then, let me reiterate what I understood from your recommendations is that we are to add a global config to control where the nonced directive will appear.
Is that correct? If so, with that options? enforce, report-only, none? And what would be a good name for this config?
Is a README warning about this specific condition warranted?

@oreoshake
Copy link
Contributor

If so, with that options? enforce, report-only, none? And what would be a good name for this config?

That sounds good to me. Is the none use case for transitioning from nonces to hashes?

And what would be a good name for this config?

🤔 naming is hard. nonces_applied_to? apply_nonces_for? nonce_mode? How do any of those sound to you?

This kinda points to a related problem in that this setting would apply to script and style nonces alike, but thankfully nobody actually uses style nonces in a non-trivial scenario (right?).

Is a README warning about this specific condition warranted?

I've added a small note to https://github.com/github/secure_headers/blob/main/docs/per_action_configuration.md#nonce. When we have the new functionality, we can specify the options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants