5 ms·
CSP is really great at plugging these kinds of security holes, but it flummoxes me that most developers and designers don't take them seriously enough to implem
by theandrewbailey 2y ago
CSP is really great at plugging these kinds of security holes, but it flummoxes me that most developers and designers don't take them seriously enough to implement properly (styles must only be set though <link>, and JS likewise exists only in external files). Doing any styling or scripting inline should be frowned upon as hard as table-based layouts.
- pocketarc 2y ago> should be frowned upon as hard as table-based layouts I absolutely agree with you. I've been very very keen on CSP for a long time, it feels SO good to know that that vector for exploiting vulnerabilities is plugged. One thing that's very noticeable: It seems to block/break -a lot- of web extensions. Basically every error I see in Sentry is of the form of "X.js blocked" or "random script eval blocked", stuff that's all extension-related.
- chrismorgan 2y ago> Doing any styling or scripting inline should be frowned upon as hard as table-based layouts. I strongly disagree: inlining your entire CSS and JS is absurdly good for performance, up to a surprisingly large size. If you have less than 100KB of JS and CSS (which almost every content site should be able to, most trivially, and almost all should aim to), there’s simply no question about it, I would recommend deploying with only inline styles and scripts. The threshold where it becomes more subjective is, for most target audiences, possibly over half a megabyte by now. Seriously, it’s ridiculous just how good inlining everything is for performance, whether for first or subsequent page load; especially when you have hundreds of milliseconds of latency to the server, but even when you’re nearby. Local caches can be bafflingly slow, and letting the browser just execute it all in one go without even needing to look for a file has huge benefits. It’s also a lot more robust. Fetching external resources is much more fragile than people tend to imagine.
- allan_s 2y agonote that for inline style/script, as long as you're not using `style=''` or `onclick=''` , you can use `nonce=` to have a hash and to my understanding, newly added inline script will not be tolerated, allowing to have the best of both world
- LegionMammal978 2y agoIt does seem like CSP nonces do not play well with caching (since they must have a different value on each page load), which would make them a detriment to performance.
- SahAssar 2y agoYou can also include a hash of the contents in the CSP, which plays well with caching.
- LegionMammal978 2y agoTrue, a hash works as a good alternative. (Unless you're doing super weird stuff like generating inline scripts at runtime.)
- eru 2y agoI think that's a limitation of our implementations. In principle, it's just bytes that we shoving down the pipe to the browser, so it shouldn't matter for performance whether those bytes are 'inline' or in 'external resources'. In principle, you could imagine the server packing all the external resources that the browser will definitely ask for together, and just sending them together with the original website. But I'm not sure how much re-engineering that would be.
- erikerikson 2y agoIn principle there's no difference between principle and practice.
- eru 2y agoSimple models are still useful: understanding exactly how and why they fail is instructive. There's a reason spherical cows in a vacuum come up again and again.
- Perseids 2y agoThis feature actually existed (see https://en.wikipedia.org/wiki/HTTP/2_Server_Push https://en.wikipedia.org/wiki/HTTP/2_Server_Push ) but was deemed a failure unfortunately (see https://developer.chrome.com/blog/removing-push https://developer.chrome.com/blog/removing-push )
- eru 2y agoThanks for the links! Yes, my comment was based of a vague recollection of this kind of thing. I'll read up on the '103 early hints' and 'preload' and 'preconnect' which might be close in enough practice.
- theandrewbailey 2y agoIt's called Content Security Policy, not Content Performance Policy. My thoughts: 1. Inlining everything burns bandwidth, even if it's 100KB each. (I hope your cloud hosting bills are small.) External resources can be cached across multiple pageloads. 2. Best practice is to load CSS files as early as possible in the header, and load (and defer) all scripts at the end of the page. The browser can request the CSS before it finishes loading the page. If you're inlining scripts, you can't defer them. 3. If you're using HTTP/2+ (it's 2025, why aren't you?[0]), the connection stays open long enough for the browser to parse the DOM to request external resources, cutting down on RTT. If you have only one script and CSS, and they're both loaded from the same server as the HTML, the hit is small. 4. As allan_s mentioned, you can use nonce values, but those feel like a workaround to me, and the values should change on each page load. > Local caches can be bafflingly slow, and letting the browser just execute it all in one go without even needing to look for a file has huge benefits. Source? I'd really like to know how and when slow caches can happen, and possibly how to prevent them. [0] Use something like nginx, HAProxy, or Cloudflare in front of your server if needed.
- bgirard 2y ago> Source? I'd really like to know how and when slow caches can happen. I don't have a source I can link to or share. But cache outliers are a real thing. If you aggregate Resource Timing results, you'll find some surprising outliers in that dataset where transferSize=0 (aka cached load on Chrome). You'll have users with a slow/contended disk where as they might have a fast link, but you'll also have the reverse where you'll have users with a fast cache and a slow network link (high latency, low bandwidth or both). There's no universal answer here and I feel like the above poster tries to oversimplify a complex problem into one-size-fits-all answers. You'll have different users making up your distribution and you'll have to decide how you weight optimizations. This could very much depend on your product, the expectations and if your user are power users running a complex SaaS frontend, or a news site supporting a range of mobile devices. A few years ago I traced and notice that Chrome has a pseudo O(n^2) behavior when pulling a bunch of sequential resources from its cache. I reported it but I'm not sure if it got fixed.
- 2y ago
- bgirard 2y ago> If you have less than 100KB of JS and CSS (which almost every content site should be able to, most trivially, and almost all should aim to), there’s simply no question about it Do you have data to back this up? What are you basing this statement on? My intuition agrees with you for the reasons you state but when I tested this in production, my workplace found the breakeven point to be at around 1KB surprisingly. Unfortunately we never shared the experiment and data publicly.
- deleted 2y ago[deleted]
- deleted 2y ago[deleted]
- wizzwizz4 2y agoI would expect it to be closer to 1KB, as well. 100KB is (at time of writing) about 5× the size of this webpage, and this doesn't load instantly for me.
- athanagor2 2y agoHonest question: I don't understand how forbidding inline scripts and style improves security. Also it would be a serious inconvenience to the way we distribute some of our software right now lol
- theandrewbailey 2y agoCSP tells the browser where scripts and styles can come from (not just inline, but origins/domains, too). Let's pretend that an attacker can inject something into a page directly (like a SQL injection, but HTML). That script can do just about anything, like steal data from any form on the page, like login, address, or payments, or substitute your elements for theirs. If inline resources are forbidden, the damage can be limited or stopped. https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
- magicalhippo 2y agoStill recall the classic forum exploits of including Javascript in your signature or similar, before such software started escaping input.
- bryanrasmussen 2y agosounds weird to me too, although I guess there could be a script that was not allowed to do CORS that then instead created an inline script and did its CORS stuff in that script - about the only way I can think of it being bad.
- diggan 2y ago> although I guess there could be a script that was not allowed to do CORS that then instead created an inline script and did its CORS stuff in that script Wouldn't even matter, as it's the origin of wherever it ends up being executed that matters, not where the code was loaded from. So JS code loaded from cdn.jquery.com on mywebsite.com would have the origin mywebsite.com, even if loaded with a typical <script> tag. In short, CORS applies to network requests made by scripts, not to the scripts themselves
- myko 2y agoI find not being able to use inline styles extremely frustrating
- sebazzz 2y ago> it flummoxes me that most developers and designers don't take them seriously enough to implement properly (styles must only be set though <link>, and JS likewise exists only in external files). Doing any styling or scripting inline should be frowned upon as hard as table-based layouts. At our place we do abide by those rules, but we also use 3rd party components like Telerik/Kendo which require both unsafe-inline for scripting and styling. Sometimes you have no choice laxing your security policy.
- midtake 2y agoWhy? If you're the content owner, you should be able to. If you factor out inline code, you will likely just trust your own other domain. When everything is a cdn this can lead to less security not more. Do you mean people should be banned from inlining Google Analytics or Meta Pixel or Index Now or whatever, which makes a bunch of XHRs to who knows where? Absolutely! But nerfing your own page performance just to make everything CSP-compliant is a fool's errand.