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

Modify CSP headers to allow hash of injected script #14233

Closed
wants to merge 24 commits into from
Closed

Modify CSP headers to allow hash of injected script #14233

wants to merge 24 commits into from

Conversation

Pandapip1
Copy link

@Pandapip1 Pandapip1 commented Mar 28, 2022

@Pandapip1 Pandapip1 requested a review from a team as a code owner March 28, 2022 17:36
@Pandapip1 Pandapip1 requested a review from digiwand March 28, 2022 17:36
@github-actions
Copy link
Contributor

github-actions bot commented Mar 28, 2022

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@Pandapip1
Copy link
Author

Pandapip1 commented Mar 28, 2022 via email

@Pandapip1
Copy link
Author

Pandapip1 commented Mar 28, 2022 via email

@Pandapip1
Copy link
Author

Hold on CI is stuck. Rerunning...

@MetaMask MetaMask unlocked this conversation Mar 29, 2022
@darkwing
Copy link
Contributor

@Pandapip1 Could you provide context for this change? Otherwise this PR isn't something we can accept.

@mrnerdhair
Copy link

mrnerdhair commented Mar 29, 2022

The context here is MetaMask/detect-provider#31. (TL;DR: Firefox applies CSP to code injected by extensions, which means that if you don't include 'unsafe-inline' you can't use e.g. window.ethereum with a CSP.)

This is very interesting code and a novel approach, and I appreciate it for that -- I can see myself referring back to this work on occasion.

However, I'm not yet convinced this approach can work in all cases. CSPs can be -- and in many notable usecases, are -- set by meta tags in addition to headers. In fact, CSP meta tags can be constructed, injected, and altered after page load by scripts, which is a technique used by all-in-one cookie consent toolkits -- if you turn off consent for a certain site, they'll just update the CSP to block it.

Preemptively adding a CSP when none exists will probably break pages that don't use one, and reliably detecting meta tag CSP's doesn't seem possible. (I'd also want to verify where this filter is applied during the ServiceWorker lifecycle; if the modifications are visible to the ServiceWorker itself, that could cause problems too.) The best solution to this issue that I can see at the moment would be to update MetaMask/detect-provider to use its own inpage-provider if it doesn't see one injected by the extension.

@Pandapip1
Copy link
Author

I'll add code to fix that. I think the approach may still work.

@Pandapip1
Copy link
Author

Pandapip1 commented Mar 30, 2022 via email

@Pandapip1
Copy link
Author

Pandapip1 commented Mar 30, 2022 via email

@Pandapip1
Copy link
Author

Pandapip1 commented Mar 30, 2022 via email

@digiwand
Copy link
Contributor

digiwand commented Mar 30, 2022

Hello @Pandapip1! I will need to allocate more time to review this thoroughly.MetaMask/detect-provider is outside my current domain and is related to this change. In the meantime, I've bumped this PR in our Slack channel for others to review.

[edit] As this PR is still work in progress (WIP), I would like to withhold my personal review until it is ready. I recommend setting this PR to "draft" until it is ready.

@Pandapip1
Copy link
Author

Haha, found the issue:
image

@Pandapip1
Copy link
Author

I can't reproduce the error on Circle CI, so I've just put the code that's erroring in a try/catch. If this passes CI, I'll test it.

@Pandapip1
Copy link
Author

CI just passed. I'm testing to see if this works.

@Pandapip1
Copy link
Author

I think this is ready for review. I actually can't currently test this, but I'm pretty confident that the code will work (and I'll test it later). If it doesn't, then I'll just make the needed changes.

@mrnerdhair
Copy link

I don't think this will work. Note from https://w3c.github.io/webappsec-csp/#meta-element:

Note: Modifications to the content attribute of a meta element after the element has been parsed will be ignored.

@Pandapip1
Copy link
Author

Pandapip1 commented Apr 1, 2022

I don't think this will work. Note from https://w3c.github.io/webappsec-csp/#meta-element

Well then... firefox doesn't follow the spec :)

I've tested the meta-modifying code, and it works as expected (see #14233 (comment))

EDIT: As you yourself said,

In fact, CSP meta tags can be constructed, injected, and altered after page load by scripts

(emphasis added)

@Pandapip1
Copy link
Author

Well, this is interesting:
image
It looks like it should be correctly modifying the headers, but it isn't. I wonder if it's to do with the following:

However, the Content-Security-Policy header is treated differently; its values are combined to apply all the specified policies. But, if two extensions set a CSP value that conflicts, the CSP service makes the restriction more strict to resolve the conflict. For example, if one extension sets img-src: example.com, and another extension sets img-src: example.org, the result is img-src: 'none'. Merged modifications always lean towards being more restrictive, though an extension may remove the original CSP header.
(https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onHeadersReceived)

I might have to do a bit of tweaking to make this work.

@Pandapip1
Copy link
Author

Okay, so my plan of action is to have the background page, instead of modifying the CSP header, delete it and send it to the content script, which then re-adds it.

@Pandapip1
Copy link
Author

Pandapip1 commented Apr 4, 2022

I think that this should work. Can someone test this?

I've got example webpages set up at:
https://CSPTest.pandapip1.repl.co/cspheader (CSP Header)
https://CSPTest.pandapip1.repl.co/cspmeta (CSP Meta Tag)

@Pandapip1
Copy link
Author

This no longer changes the provider code (I think). Would someone mind reviewing it?

This might also fix #13972. I will also test that.

@Pandapip1
Copy link
Author

Pandapip1 commented Apr 5, 2022

Why is the CLA bot failing?

EDIT: It fixed itself.

@Pandapip1
Copy link
Author

Good news: it injects web3 all the time
Bad news: it isn't re-adding the CSP

@Pandapip1 Pandapip1 closed this Aug 19, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
DO-NOT-MERGE Pull requests that should not be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow working with strict CSPs Inpage injection fails in Firefox under some CSP settings
4 participants