question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CSP: update modal-chooser so that it loads js source from URL using <script> rather than using eval()

See original GitHub issue

the modal-chooser currently uses a mechanism that loads modal HTML+JS from a single URL as json response, then extracts the HTML as raw string and injects it into the page, and then extracts the JS as raw string and turns it into executable code using eval().

The first part might be dangerous, because it might lead to injecting user-generated html (note: I’m not sure, didn’t look deeply enough into it), but the second part violates CSP something fierce, so seeing if it’s possible to rework this a little to load the associated javascript as a dedicated URL output using a <script> tag so that sensible CSP settings don’t break wagtail would be a good idea.

I’m having a quick look at this focussing specifically on the images/chooser use case:

  • leave the images/chooser route as is
  • add an images/chooser/js route for exclusively serving the JS content with the correct mime-type
  • keep the modal-chooser as extracting and injecting HTML
  • change the modal-chooser to load the JS by instead creating a <script src="..."></script> and adding that to the document <head>

That might still trip up CSP, but hopefully it doesn’t.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
Pomaxcommented, Mar 7, 2018

While I agree that doing the right thing is more important than “following the rules”, production installs by companies like Mozilla simply can’t be set up if unsafe-eval is necessary, so there’s a middle ground here where I can write this PR that first makes the code “do what it does, just a little differently, without violating CSP” so that wagtail can be deployed while ticking the boxes (fairly literally: there is a security anlysis review with checkboxes that in fact do need ticking before something can go live =), which at least improves the CSP violations for people right now, followed by a proper bigger rewrite that makes wagtail serve as much static JS up front as possible instead of sending it over call-by-call.

I personally dislike CSP but the reality is that a lot of companies rely on it, and cannot deploy services without a strong CSP in place (and without the freedom to run the /admin routes on a completely different domain), so if that’s a reason they can’t use wagtail that feels like a good thing to first fix “so things work” followed by a second fix “so that things work really well”.

At the very least, eval() is never a good thing, and rewriting the code a bit so that rather than eval(), a normal script element is built, should sidestep the CSP violation errors with relatively minimal impact to the current state of the code. That’ll be a smaller PR than what I suggested above, so I’ll see about filing that first.

(I’m having a bit of difficulty getting things set up for dev as recommended by the docs - vagrant is not even remote cooperating with me right now)

1reaction
gasmancommented, Mar 7, 2018

Hi @Pomax,

If we’re going to try to follow CSP rules, I’m keen that we should respect the intent of those rules (i.e. “don’t serve dynamically-constructed JS code”) rather than treating it as a box-ticking exercise (“don’t use eval”). I’m concerned that the approach proposed here isn’t doing that: we’re still sending dynamically-constructed JS responses (which may contain untrusted strings from user input) and just finding another way of evaluating them that avoids eval. If anything, setting CSP headers without dealing with the underlying issue makes it more dangerous, since we’re claiming a level of “trustedness” for our JS code that we can’t really ensure. (I’m also worried that if we have to add hacks to make it work, such as stashing things in global variables between requests, then we’re adding more opportunities for things to break, rather than making the code more secure.)

If a sysadmin / hosting provider is requiring the use of CSP, then rather than trying to sneak past the policy on a technicality, I think it’s more responsible for us to be upfront about it, and say “we can’t reasonably follow this policy in spirit; if our use of dynamic JS raises concerns about the security of the code, you should take alternative steps to mitigate it, such as putting the admin behind a separate locked-down domain”.

I think the modal views could (and should) be refactored to use a single fixed JS handler that receives pure JSON data on each step to tell it what to do next, rather than serving up a new dynamic JS handler on each step. (I know this is a bigger change than what you’re proposing, but I think it’s necessary as a step towards dealing with CSP ‘properly’, rather than working around it.)

More generally, my overall impression of CSP is that it assumes a model of application where the client-side behaviour is entirely fixed at build time, which doesn’t really fit well with how Wagtail is designed. Consider something like StreamField, where the client-side behaviour is determined by configuration that exists within Python code - we currently do that with “one-liner” calls to functions defined elsewhere. To do that the “CSP way”, we’d probably have to approach it in the same way as templating libraries (as described at https://developers.google.com/web/fundamentals/security/csp/#eval_too), and add a precompilation step. Obviously, that’ll be a major rewrite, and ultimately it may not be achievable - but I think any steps we take towards CSP support will have to be aimed in that direction.

Read more comments on GitHub >

github_iconTop Results From Across the Web

CSP: script-src - HTTP - MDN Web Docs - Mozilla
The HTTP Content-Security-Policy (CSP) script-src directive specifies valid sources for JavaScript. This includes not only URLs loaded ...
Read more >
eval.call throws error in Chrome extension - javascript
call(null, src) causes the error. I have tried to include this directive in manifest V3, but I have the same error: "content_security_policy": { ......
Read more >
The CSP script-src Directive Guide - Content Security Policy
A guide to using script-src with CSP or Content Security Policy. ... The script-src Content Security Policy (CSP) directive guards the loading and...
Read more >
JavaScript eval() Method - W3Schools
With eval(), third-party code can see the scope of your application, which can lead to possible attacks. Syntax. eval(string). Parameters. Parameter ...
Read more >
So we broke all CSPs … You won't guess what happened next!
object-src 'none'; base-uri 'none';. Recap: How do CSP Nonces Work? Policy based on nonces. ▷ all <script> tags with the correct nonce attribute...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found