Closed Bug 1270157 Opened 8 years ago Closed 6 years ago

Define a Content Security Policy (CSP) for treeherder.mozilla.org

Categories

(Tree Management :: Treeherder: Infrastructure, defect, P1)

defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: emorley, Assigned: emorley)

References

(Blocks 2 open bugs)

Details

Attachments

(3 files)

Note to self: Until we're on Django 1.10, we'll need to exclude the Django admin from the CSP policy, since it used inline JS: https://github.com/django/django/commit/d638cdc42acec608c1967f44af6be32a477c239f
Some interesting research from Google on the topic: https://research.google.com/pubs/pub45542.html
Summary: Define a Content Security Policy for treeherder.mozilla.org → Define a Content Security Policy (CSP) for treeherder.mozilla.org
Bug 1311967 will make this easier due to comment 1.
Depends on: 1311967
This is higher priority now that we store the Taskcluster token in localstorage (bug 1273096), since any XSS could expose that token. (This came up as part of discussing moving the reftest analyzer into treeherder: https://github.com/mozilla/treeherder/pull/2107). I worked on this for a bit a week or two ago and have a Django middleware solution that works fairly well (though I want to test with a WhiteNoise add_extra_headers() solution too), with an initial attempt at a policy that doesn't break anything. However it's going to be the long tail of tasks (testing against the numerous WhiteNoise served static pages plus all the Django parts - eg swagger docs, django admin, d-r-f API html output, debug toolbar etc) that drags the process out (we'll probably just want to enable piecemeal).
Is it possible to fix this without breaking inline treeherder results (which are made available via BugzillaJS)? If not, we should remove that feature from the extension. See also bug 1335618 which broke them on the Bugzilla side already.
We won't be breaking features as part of fixing this bug (at least not deliberately!). The breakage on Bugzilla's bug is really quite different: it's quite tricky for them to take into account every addon people might choose to modify the page client side and insert an iframe, when designing the CS policy. For this bug, it doesn't really apply, since we're the ones serving the page, so know about it already. (We won't be using the `frame-ancestors` directive for the embed page, similar to how we already exempt it from `X-Frame-Options: DENY`: https://github.com/mozilla/treeherder/blob/e91d597ff741d0c5d6c2eb2fcf23aaac2f07a827/treeherder/embed/views.py#L9)
(In reply to Ed Morley [:emorley] from comment #7) > We won't be breaking features as part of fixing this bug (at least not > deliberately!). No worries! It's a bit of a niche feature with odd interactions, so I figured I'd mention it. Thanks.
We can now use this addon to help generate a CSP: https://github.com/april/laboratory
Both devising a suitable CSP policy and making the header be returned for all parts of the stack will be easier after bug 1433104, bug 1065784 and bug 1433011 - since that will leave only the static UI, d-r-f REST API, graphql API and swagger docs page to worry about. (And mean we don't have to fix the embeddable push status page's inline JS/...)
Depends on: 1433104, 1065784, 1433011
I took another look at this today since the issue in the CSP Laboratory extension that was previously blocking me [0] is now fixed, and the WIP branch for this is one of the many I have locally that I'd love to get cleaned up and out of the way :-) Since looking into this last... The good: * now that we've stopped using AngularJS for jobs-view/user guide/log viewer, there are much fewer parts of our codebase that need the Angular CSP readiness changes (just perfherder) * we no longer need to add exceptions for the unified-logviewer iframe now that we're using the react-lazylog package * the EOL of buildbot means fewer domains to whitelist in the connect-src policy The annoying: * it appears that the react-select package (used by `CustomJobActions.jsx` and `autoclassify/LineOption.jsx` in jobs-view) inserts inline CSS (due to it using the `emotion` CSS-in-JS package with no way to opt out), which requires the use of unsafe-inline for style-src. I'll file a bug for seeing if we can stop using this package. * the way react-hot-loader v4 is used (compared to v3) means that there is a leftover eval-check that doesn't do anything, but triggers a false-positive unsafe-eval script-src policy violation report. However this can be fixed upstream - I'll file a separate bug. Example policy suggested by CSP laboratory for jobs-view (with adjustment to make the multiple taskcluster domains a wildcard instead): default-src 'none'; connect-src 'self' https://auth.mozilla.auth0.com https://*.taskcluster.net https://bugzilla.mozilla.org https://hg.mozilla.org https://treestatus.mozilla-releng.net; font-src 'self'; img-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' ...so clearly need to fix the above issues (unsafe-*) before there is any point doing this. [0] https://github.com/april/laboratory/issues/17
Depends on: 1507903
Depends on: 1507906

I have a WIP for this locally. I think we should proceed with this even though we're waiting on bug 1507903, since we can always use unsafe-inline for CSS for now on the main job view and remove it later once the bug is fixed.

Assignee: nobody → emorley
Status: NEW → ASSIGNED
Priority: P3 → P1

The first part of this has landed, which adds a report-only CSP header and an API endpoint for collecting violation reports:
https://github.com/mozilla/treeherder/commit/5b7209be2914fd1b1f5a3e5125b33c7b6d06b701

Any violation reports will be visible here:
https://insights.newrelic.com/accounts/677903/explorer/events?eventType=CSP%20violation&duration=604800000

Once this has been deployed to production, and we're happy that the policy is not too strict (ie blocking things we shouldn't be), we can switch it to being a full CSP header and not the report-only version, so it actually starts taking effect.

Blocks: 1529862
No longer depends on: 1507903

Hi April - hope you are well.

I don't suppose you could help us with some strange issues we're seeing now that we've added a Content-Security-Policy-Report-Only header? In the collected CSP violation reports, I see instances like:

{
  "blocked-uri": "https://queue.taskcluster.net/v1/task/ckSi7VV8TnGBsOgIQctG3Q/artifacts/public%2Factions.json",
  "document-uri": "https://treeherder.mozilla.org/",
  "original-policy": "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self' https://*.taskcluster.net https://treestatus.mozilla-releng.net https://bugzilla.mozilla.org https://auth.mozilla.auth0.com; report-uri https://treeherder.mozilla.org/api/csp-report/",
  "referrer": "https://treeherder.mozilla.org/perf.html",
  "violated-directive": "connect-src"
}

This doesn't make sense to me, since the supposed violation is something permitted by the existing connect-src rule. The report was submitted by a User Agent of Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:65.0) Gecko/20100101 Firefox/65.0.

Is this a bug in Firefox, or an issue with our policy?

Flags: needinfo?(april)

(In reply to Ed Morley [:emorley] from comment #15)

This doesn't make sense to me, since the supposed violation is something permitted by the existing connect-src rule

Ah so it turns out that if the fetch() gets an HTTP 301/302 redirect, then:

  • both the original and new domains need to be whitelisted in the connect-src directive
  • unhelpfully neither the fact that a redirect occurred nor the value for the new domain is included in the CSP violation report sent to report-uri

In our case the queue.taskcluster.net URL was redirecting to taskcluster-artifacts.net.

Sorry for the noise! :-)

Flags: needinfo?(april)

Additional items added to the report-only CSP header in:
https://github.com/mozilla/treeherder/commit/7833ba2bb755d0c7e9e4e223b4b132045090cd45

The CSP collector updated to skip CSRF checks, so it still works in browsers that send the Django session cookie but not the CSRF token [1], in:
https://github.com/mozilla/treeherder/commit/d5494a7848d46cfc7650281613e6a3ef778f26ba

[1] This issue wasn't noticed before since Firefox doesn't send the session cookie due to platform bug 1140266, whereas Chrome does.

Glad I could help. :)

One quick thing that can help with issues like this is to install Laboratory and see what CSP it spits out:
https://addons.mozilla.org/en-US/firefox/addon/laboratory-by-mozilla/

It should spit out a connect-src that covers both of them, which can be helpful for debugging these weird kinds of issues.

(In reply to April King [:April] from comment #19)

One quick thing that can help with issues like this is to install Laboratory and see what CSP it spits out:
https://addons.mozilla.org/en-US/firefox/addon/laboratory-by-mozilla/

It should spit out a connect-src that covers both of them, which can be helpful for debugging these weird kinds of issues.

Unfortunately Laboratory was what gave the incorrect header in this case. I filed:
https://github.com/april/laboratory/issues/20

CSP report-only header converted to the real header in:
https://github.com/mozilla/treeherder/commit/d9de41bf4b4e06acebc3a801cba2629763801b44

NB: When features are added in the future, PR authors and reviewers will need to remember to factor in updating the policy if needed (for example to add domains to the connect-src directive). The CSP header is not enabled when using webpack-dev-server (it would break dev source maps and react-hot-loader) so if in doubt test locally (using yarn build and serving via Django runserver) or on prototype first.

Bug 1529862 is filed for removing 'unsafe-inline' from the style-src directive.

Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED

Well shucks. That's embarrassing. I'll see why that's happening now. Thanks for the nice bug report.

No worries!

(Separately) Checking HTTP observatory after this landed shows our score increased from a B to an A+ :-)

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

Attachment

General

Created:
Updated:
Size: