Improve overall frontend security of pontoon

RESOLVED FIXED

Status

Webtools
Pontoon
P2
normal
RESOLVED FIXED
a year ago
a year ago

People

(Reporter: April, Assigned: mathjazz)

Tracking

(Blocks: 2 bugs)

Trunk
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(URL)

(Reporter)

Description

a year ago
Hello hello!  It's your friendly neighborhood infosec engineer, April!

I was hoping we could make some improvements to the security of pontoon.mozilla.org.  I know you're not on the bug bounty list, but having good security should hopefully keep bugs from arriving on your doorstep in the future.  :)

A couple things should probably be (hopefully) relatively simple:

```
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
```

HSTS helps ensure that users only visit the site over HTTPS, and XCTO disables browser MIME type sniffing.

I'd also like to get CSP going on pontoon as well.  This can significantly decrease the rate of cross-site scripting issues, a large part of our bug bounty payouts, and a frequent bug source for pontoon.

I've been working on this one for a while.  I think it should go a long way towards fixing all the self-xss/xss bugs in pontoon.  Everything seems to work fine and I don't get any errors.  That said, I don't know all of the nooks and crannies of pontoon, so I might have missed something.

  Content-Security-Policy: default-src 'none'; connect-src 'self'; font-src 'self'; frame-src 'self'; img-src 'self' https://*.wp.com/pontoon.mozilla.org/ https://ssl.google-analytics.com https://www.gravatar.com/avatar/; script-src 'self' https://login.persona.org 'sha256-x3niK4UU+vG6EGT2NK2rwi2j/etQodJd840oRpEnqd4=' 'sha256-fDsgbzHC0sNuBdM4W91nXVccgFLwIDkl197QEca/Cl4=' https://ssl.google-analytics.com/ga.js; style-src 'self' 'unsafe-inline'

Those two hash sources cover inline javascript.  One of them is the Google Analytics bit, and the other is a Persona bit.  Those hashes definitely work great for pontoon.mozilla.org, but might not work for dev versions if you have different GA keys, for example.

Thanks so much!  Please let me know if you have any questions!  With this, I'd like to think we can get pontoon.mozilla.org up to a much better score on the Observatory:
(Assignee)

Comment 1

a year ago
April, thank you so much for these very valuable recommendations to improve Pontoon security!

I think I have a pull request more or less ready, do you wanna have a look?
https://github.com/mozilla/pontoon/pull/477
Assignee: nobody → m
Priority: -- → P2
(Reporter)

Comment 2

a year ago
Looks great to me!  All I would add is to make sure to test the staging site thoroughly before rolling out CSP.  Like I said, everything seemed great to me, but I might have missed a source on some little nook of pontoon that I didn't know about.

Otherwise, that's a fantastic turnaround!  Nice work!
(Assignee)

Comment 3

a year ago
Phew, I'm actually no longer sure we can use CSP. Pontoon loads websites inside an iframe, to make them localizable "in place". They can come from any HTTPS-based URL and they can load any resource from any URL. 

Is it somehow possible to allow child-src (frame-src seems deprecated) for all domains?
Flags: needinfo?(april)
(Reporter)

Comment 4

a year ago
You totally can!  If you know that it's only going to be HTTPS, you can do child-src https:.  Or if you need to work with both http and https, you can do child-src *.  I would actually recommend replicating child-src into frame-src, for older browsers that only support CSP1.

Overall, this would look like:
Content-Security-Policy: default-src 'none'; child-src https:; connect-src 'self'; font-src 'self'; frame-src https:; img-src 'self' https://*.wp.com/pontoon.mozilla.org/ https://ssl.google-analytics.com https://www.gravatar.com/avatar/; script-src 'self' https://login.persona.org 'sha256-x3niK4UU+vG6EGT2NK2rwi2j/etQodJd840oRpEnqd4=' 'sha256-fDsgbzHC0sNuBdM4W91nXVccgFLwIDkl197QEca/Cl4=' https://ssl.google-analytics.com/ga.js; style-src 'self' 'unsafe-inline'
Flags: needinfo?(april)
(Reporter)

Comment 5

a year ago
Actually if you need both http and https, it's probably best to have child-src http: https:; frame-src http: https:.  That would restrict you from framing protocols other than http, if that is even possible.  
(Assignee)

Comment 6

a year ago
Ohhh, you can do *that*! Thanks! Works!

BTW, do you have any idea why does the 'Session cookie set without using the Secure flag or set over http' test on Observatory fail for pontoon.mozilla.org, but not for mozilla-pontoon-staging.herokuapp.com? It's the same codebase, the only difference is that Stage uses Heroku URL.
(Reporter)

Comment 7

a year ago
It's because pontoon.mozilla.org is setting a "heroku-session-affinity" cookie that the Observatory is, erroneously in this case, detecting.  Either adding the Secure flag to it or enabling HSTS should fix that problem, or at least lower the penalty.

Comment 8

a year ago
Commit pushed to master at https://github.com/mozilla/pontoon

https://github.com/mozilla/pontoon/commit/246d98719c3243ce3f6a6ca729011415190d6f1b
Fix bug 1308645: Improve frontend security (#477)

By adding the following headers:
* Strict-Transport-Security: max-age=63072000
* X-Content-Type-Options: nosniff
* x-xss-protection: 1; mode=block
* Content-Security-Policy

Updated

a year ago
Status: NEW → RESOLVED
Last Resolved: a year ago
Resolution: --- → FIXED
(Assignee)

Comment 9

a year ago
I had to temporarily revert this patch, due to an error with Persona login. You can reproduce it on Stage by tying to sign in with Persona: https://mozilla-pontoon-staging.herokuapp.com/sl/.

Instead of openning the popup, nothing happens - but you'll see the CSP error in the Console.

I tried to fix the issue but I can't figure out how. The 'sha256-fDsgbzHC0sNuBdM4W91nXVccgFLwIDkl197QEca/Cl4=' hash represents the Persona inline script. Unless it's not the right hash? Replacing all 'sha-256' rules with 'unsafe-inline' fixes the problem, but I'd like to avoid that.

Any hints?
(Reporter)

Comment 10

a year ago
It will tell you the proper hash in the console.  Do you use different inline scripts between staging and production?  I had only gotten the hash for production.
(Assignee)

Comment 11

a year ago
I'm looking in the devtools (right?) console and can't find the hash.

It's the same script in all environments, so I can reproduce the issue in all of them.
(Reporter)

Comment 12

a year ago
I don't know if it's actually the hash at the bottom; usually those will get errors on page load.  I see this sort of error more often when something is trying to set an event handler directly on an element (elem.onclick = function), instead of via addEventListener.

To verify that it's not Persona, the first step would be to disable CSP for script-src (or leave 'unsafe-inline' on) and move the Persona code to an external javascript file.  See if that works, and then try enabling CSP again.  Or if you know where your event handlers are set, check to see that they're set properly.
(Reporter)

Comment 13

a year ago
* actually the <script> at the bottom, rather.

Comment 14

a year ago
Commit pushed to master at https://github.com/mozilla/pontoon

https://github.com/mozilla/pontoon/commit/6886b0ed334cd39843c09c2d14e7712b10b72a6b
Revert "Fix bug 1308645: Improve frontend security (#477)"

This reverts commit 246d98719c3243ce3f6a6ca729011415190d6f1b.
(Assignee)

Comment 15

a year ago
To leave the trace in Bugzilla: the problem was caused by the javascript: code being called from the href attributes. This should fix it: https://github.com/mozilla/pontoon/pull/480/commits/841f57d5c4173e391a76b01efac587493751e271.

Comment 16

a year ago
Commit pushed to master at https://github.com/mozilla/pontoon

https://github.com/mozilla/pontoon/commit/2116b2943a1e8fee096257f3802e555f48b83a51
Fix bug 1308645: Improve frontend security (#477)

* Stop using JS in href attributes (Persona sign in blocked by CSP)
* Fix CSP-related homepage framing issues on a local setup using HTTP
You need to log in before you can comment on or make changes to this bug.