Open Bug 1588957 Opened 5 years ago Updated 2 years ago

Websites can observe CSP violations from content scripts

Categories

(WebExtensions :: General, defect, P2)

defect

Tracking

(Not tracked)

People

(Reporter: mixedpuppy, Unassigned)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

(Whiteboard: [addons-jira])

Attachments

(2 files)

If an addon content script triggers a violation against a pages csp the page can be notified via cspviolationevent. This can happen via content.fetch in the content script.

This bug followed from the thread at https://phabricator.services.mozilla.com/D48107?id=176093#inline-298599

In that thread, I didn't ask for a change in functionality, but to add explicit checks to make sure that cspviolationevent is fired iff the event is expected for the individual test cases in that file. So if a request was blocked by the content script's CSP, then the event should not fire (otherwise, if blocked by the page, the event should fire).

I assumed that that was already the behavior of that current patch, but if not, then we should indeed look into it.

content.fetch is documented to behave as if it were to be called by the page (well, without extension permissions), so triggering a cspviolationevent when it's blocked doesn't look too wrong to me.

Then this will likely be closed at some point.

Given the amount of tests for the violation event, I doubt that there is an issue with pages getting those, the concern is more that pages don't get moz-extension violations. however I just modified the test.

Priority: -- → P3

Resetting priority for triage. This should be a higher priority as this is not only visible in cspviolationevent events, but also in CSP reports (report-to / report-uri). CSP reports can be triggered even when JavaScript is disabled on a website.

These CSP reports include the URL of the script that triggered the failure, in the case of extensions that's the moz-extension://UUID format, which can be abused for fingerprinting (like bug 1405971).

CSP violations triggered by content scripts should ideally not be reported to the website, or at least the extension UUID should be sanitized.
CSP violation events should ideally still be triggered in the content script for extensions, to allow them to work. This may be difficult since the target of the CSP violation event is a DOM element, the content script and the web page share the same document object (inside the content script sandbox, the document is seen with Xray vision though).

Severity: normal → --
Type: task → defect
Priority: P3 → --
Summary: determine if we should change csp reporting for content scripts → Websites can observe CSP violations from content scripts
Flags: needinfo?(mixedpuppy)

Christoph, can you help outline what should happen to filter extension csp violations?

Flags: needinfo?(mixedpuppy) → needinfo?(ckerschb)

I would have thought we only report the scheme, in that case moz-extension as the blocked-uri or also document-uri because we call StripURIForReporting for both of those. Is that not what's happening?

Or is it the sourcefile, line-number, and column-number that leaks info? I guess we could surpress that info in case of a moz-extension scheme. Or is there yet something else?

Flags: needinfo?(ckerschb)
Severity: -- → S2
Priority: -- → P2

I looked into (and tested) this.

a) we don't expose moz-ext in any reports that go to the report-uri, at least not in any of the test coverage that we have (e.g. test_ext_contentscript_csp.js).
b) the proposal to have content scripts receive violation reports, but not the page, seems pretty difficult when using content.fetch (etc).

While a content script can trigger a violation report in the page and to the report-uri, I do not see any leaked data (other than the ping itself).

These CSP reports include the URL of the script that triggered the failure, in the case of extensions that's the moz-extension://UUID format

Rob, do you have an STR that produces that? Or was this just an assumption?

Flags: needinfo?(rob)

STR is a content script that injected an inline script tag.

STR:

  1. Install version 4.23.1 of https://addons.mozilla.org/en-US/firefox/addon/dont-track-me-google1/versions/
  2. Visit google.com
  3. Open the console, and look for errors and/or network requests.

Expected:

  • No CSP errors

Actual:

  • Error in console: Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).
  • Network request to the cspreport endpoint at consent.google.com with the following request body (formatted for readability):
{
  "csp-report": {
    "blocked-uri": "inline",
    "column-number": 48,
    "document-uri": "https://consent.google.com/intro/?continue=https://www.google.com/?gws_rd%3Dssl&origin=https://www.google.com&if=1&gl=NL&hl=nl&pc=s",
    "line-number": 372,
    "original-policy": "script-src 'nonce-/Ga0rEw7ulvlYYM7QbOYOw' 'unsafe-inline'; object-src 'none'; base-uri 'self'; report-uri https://consent.google.com/_/ConsentUi/cspreport; worker-src 'self'",
    "referrer": "https://www.google.com/",
    "source-file": "moz-extension://671262ee-f895-4ee8-b175-a3fc2b9aae38/contentscript.js",
    "violated-directive": "script-src"
  }
}
Flags: needinfo?(rob)

This test isn't how we want it in a final patch, but it does throw right now.

We have also encountered this issue in the DuckDuckGo extension and will be shipping a fix to block reports with moz-extension:// URLs in our next release.

We consider this a critical issue, as it exposes a strong user identifier to sites which persists history/storage clearances. Additionally, if an affected extension is enabled in private windows, this identifier is persisted there. A test page which demonstrates the issue is available here: https://privacy-test-pages.glitch.me/security/csp-report/index.html. Using this we found several other popular extensions leaking extension IDs this way:

  • Adguard
  • AdBlocker Ultimate
  • Privacy Badger
  • LastPass
  • Dark Reader
  • SingleFile

Note, some extensions, like uBlock Origin, block all csp-reports and therefore protect against this.

Depends on: 1705523

With the patch from bug 1705523, the UUID won't be leaked any more. CSP reports will then look like "source-file": "moz-extension".

I'll leave this bug open for the purpose of preventing CSP reports for extension scripts.
The CSP spec generally states that extensions should be exempt from the CSP.
But failing that, the least that we can do is to not generate CSP violation reports for it (like Chrome does).

The CSP spec generally states that extensions should be exempt from the CSP.

Is that bug 1267027?

(In reply to Alexei from comment #11)

The CSP spec generally states that extensions should be exempt from the CSP.

Is that bug 1267027?

Yes. Specifically the text quoted at https://bugzilla.mozilla.org/show_bug.cgi?id=1267027#c20

Depends on: 1707107

For people who are following this bug: until this bug is resolved, CSP violations from extensions can still trigger reports.

Although the patch from bug 1705523 will prevent the UUID from leaking, it doesn't prevent CSP reports from happening. So if your extension injects a (dynamically generated or static) inline script, and the website has enabled the "report-sample" directive, then the start of the inline script will be reported to the CSP endpoint. That's problematic if the inline script contains sensitive data.

Note that extensions shouldn't be injecting sensitive data via inline scripts anyway, even without CSP violation reports they could detect inline scripts via mutation observers.

Dropping S3 to S2 because the UUID leak has been resolved (comment 10). As comment 13 noted, there is still the report-sample leak (but even if that is fixed, mutation events can still be used to extract the info, unless the <script> is part of a closed shadow DOM tree).

There has been work to identify the CSP to use for extension-inserted content (bug 1267027). It should be feasible to at least stop propagation of these violations to web pages. Secondarily, it would be nice if extensions can detect violations within their content script, but that is not a must-have blocker for this bug.

Side note: if we can reliably associate inline <script> with extension CSP, then it would be nice to make it independent of web pages (or at least for window.eval - bug 1591983), since that appears to be the canonical way to run scripts in the page's content from a content script (also relied upon in the initial version of the userScripts API - https://github.com/w3c/webextensions/issues/279 / https://github.com/w3c/webextensions/pull/331). I also see extensions removing the CSP with the webRequest API to get around this issue (but bug 1736575 would also be a good alternative for that use case).

I saw this bug and decided to implement a somewhat limited solution for this. It suppresses sending CSP reports and the "securitypolicyviolation" event when the source-file is a moz-extension: URL and the document is http(s). That was the best solution that I could come up with that shouldn't block it in too many cases. e.g. for data: URLs we don't necessarily know if it's running an extension or web context.

We will still show the console error in any case.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: