Htmx does not play well with content security policy
HTMX, a JavaScript framework, presents security challenges due to its handling of HTML tags and external script loading. Despite some security features, HTMX usage raises HTML injection risks, complicating full security implementation.
Read original articleHTMX, a JavaScript framework for dynamic data loading, poses challenges with Content Security Policy (CSP) and cross-site scripting (XSS) protection. HTMX's use of normal HTML tags with custom attributes makes it hard to secure against XSS attacks. Malicious code injection is a concern, as HTMX can load scripts from external sources and execute them on the page. Features like unsafe eval and configuration meta tags further complicate security measures, potentially enabling attackers to bypass CSP restrictions. While HTMX offers some security features like hx-disable and nonce support, these can be circumvented, undermining CSP protections. Overall, using HTMX increases the risk of HTML injection attacks, and achieving full security while leveraging its features remains a challenge.
Related
Hypermedia Systems
The book "Hypermedia Systems" by Carson Gross, Adam Stepinski, and Deniz Akşimşek, with a foreword by Mike Amundsen, introduces innovative web development concepts using htmx and Hyperview. It caters to web developers, individuals interested in web basics, and companies transitioning apps to mobile platforms. Available online and on Amazon.
I found a 1-click exploit in South Korea's biggest mobile chat app
A critical exploit in KakaoTalk allows attackers to run JavaScript in a WebView, potentially compromising user accounts by stealing access tokens. The exploit highlights the need to address security vulnerabilities in messaging apps.
Polyfill supply chain attack hits 100K+ sites
A supply chain attack on Polyfill JS affects 100,000+ websites, including JSTOR and Intuit. Malware redirects mobile users to a betting site. Users advised to switch to trusted alternatives like Fastly and Cloudflare.
If you're using Polyfill.io code on your site – remove it immediately
A Chinese organization acquired polyfill.io, infecting 100,000+ websites with malware. Security warnings urge removal of its JavaScript code. Google blocks ads on affected sites. CDN mirrors aim to reduce risks.
An Htmx Success Story
Discussion on transitioning from Django+React to Django+HTMX stack. Challenges with Django and React highlighted, solved with HTMX and AlpineJS. Improved simplicity, productivity, and compatibility with older devices. Transition driven by developer productivity.
I've been using htmx with CSP for the past couple of weeks, and I do find that it expands attack surface in an unpleasant way, but I do still think it brings enough value that I'm willing to rely on other protections.
>That cors.php file contains the JavaScript payload, and also sets CORS headers so that the browser has access to it.
The following htmx settings should defeat this:
htmx.config.selfRequestsOnly = true;
htmx.config.allowScriptTags = false;
htmx.config.allowEval = false;
>HTMX has functionality that automatically adds the correct nonce to inline scripts it retrieves. This is convenient, but totally breaks the security model of CSP with nonces.Agreed, this seems like an anti-feature that completely subverts CSP.
>Of course, this is trivial to bypass: just close the div tag with </div> and insert your payload outside of the element with the hx-disable attribute.
This is true, but it kind of glosses over the fact that you have to screw up a lot more to give the attacker complete control over the HTML. Usually you're not just executing attacker-controlled content as HTML. If you're using a templating system, the more likely vulnerability is that the attacker is limited to escaping an HTML attribute and adding extra one. That said, it's true that if you have a vulnerability that allows an attacker can escape one context, it's much more likely that they can escape them all.
>For these to work, the application has to allow evaluating dynamic code, using the CSP option unsafe-eval. However, allowing unsafe-eval immediately makes it possible to inject JavaScript using HTMX functionality.
I think this is the weakest point, as htmx works well without unsave-eval. I've been using it in my app without unsafe-eval. The features you lose are just convenience features for writing HTML that you can still achieve by subscribing to htmx events in JS. Yes, it means you have to write a little bit more JS, but it's much better than including unsafe-eval.
I wish that htmx would be a bit more CSP-friendly, but it's much better than other similar frameworks.
HTMX triggers do in fact use JavaScript eval(), which will get blocked with a CSP that does not allow it. But you can use standard JS scripts to add events. The same goes for inline CSS.
The “basic” golden rules:
- Only call routes you control
- Always use an auto-escaping template engine
- Only serve user-generated content inside HTML tags
- If you have authentication cookies, set them with Secure, HttpOnly, and SameSite=Lax
one great feature of htmx is how easy it is to understand and develop extensions for. I've just implemented this extension which allows safer handling of CSP nonce if this was required by an application. Hopefully this will get accepted as an official htmx extension.
My advice is if your not using inline script tags or the eval feature just keep it simple and disable allowScriptTags and allowEval and set a good CSP header. Also make sure you set a htmx-config meta tag in your page headers to set your config and protect from injected meta tags.
If you need inline scripts in a few places then be aware you need to choose a good templating or auto escaping engine on the backend to protect you and think about user inputs and be careful when using any raw escape override functions. If you have a sensitive application that needs regular external pen-testing then look at things like my safe-nonce extension that gives you another layer of protection to sell.
I'm surprised that CSPs with unsafe-inline aren't treated with the same hate that table based layouts get. They are really bad.
CSP is a mitigation for XSS vulnerabilities. Yeah, if you always sanitize everything in the right way, you won't have XSS vulnerabilities.
CSP was born out of the recognition that people fail to properly sanitize everything, even if they know that this is what they should do. Because it's complicated, and there are so many corner-cases and different ways to have XSS. CSP is a mitigation on top, in case your "we sanitize everything in the right way" goes wrong.
Making the point that you don't need CSP if you don't have XSS vulnerabilities is like saying C is secure as long as you know know how to use it and don't write code with memory safety bugs.
https://www.sjoerdlangkemper.nl/2024/06/26/htmx-content-secu...
<div hx-disable>
<%= raw(user_content) %>
</div>
So, I get that `raw` prevents htmx from being used. I get that `<script>` still works.But I find it scary that if `user_content` is `</div><div>...` that is actually injected, as raw HTML. I would expect that the `<%= raw(user_content) %> only has access to contents of the div it is in itself, and nothing more. But instead I understand that the HTML is injected as text (?) and then re-parsed (?).
I'm still searching for the holy grail of web development without Javascript or TypeScript, still not found.
Leptos still ahead but still imature, recently with panic! with signal usage. Dioxus today commited improvements to suspension such as placeholders...
egui unusable in mobile, as Android keyboard overlaps the window.
Don't know other alternatives in other languages, but for those who don't want JS it's difficult.
https://htmx.org/docs/#security
and security guide:
The "unsafe eval" and "nonces for inline scripts" sections seem like valid criticisms of how HTMX works currently. It seems both are possible to disable using the configuration, though (meaning you could remove unsafe-eval from your CSP and htmx would still work except the disabled features).
The "hx-disable" one seems like a badly designed security feature, frankly. BUT, the code that rendered the unsanitized HTML content was not htmx (looked like an erb template), so htmx shouldn't really be blamed for that one.
Loading malicious fragments: This is in no way related to htmx and is the same for all web implementations because you don't go get possible script code from random untrusted domains you don't trust or control. Also if he had tried this with the current version of htmx (2.0) he would have not been able to do this as it now defaults to blocking hx requests to external sites and you can only use local relative paths now. So win to htmx on this point.
Unsafe eval: Yeah unsafe eval looks bad but almost every other client side framework also has this same issue and it is very hard to turn this one off on any modern interactive or SPA like website today. Htmx has the option to just ignore the two features that need unsafe eval and implement these features with other more custom solutions unlike most other solutions so I have to chalk this up as a second win for htmx.
Disabling HTMX with hx-disable: I think it fair that hx-disable is not a fool proof security feature and is there to stop silly things and provide some isolation for content to separate it from htmx. But you should probably not allow un-sanitized data in here and expect this to save you.
Nonces for inline scripts: Yeah htmx has some support for nonces and they can protect from inline scripts inserted into the page somehow but they won't protect you from scripts returned from your trusted local server via hx requests by design. Another small win here.
Configuration meta tag: This one is a fair point and the use of malicious meta tags is an interesting attack vector. This may weaken some of the security features built into htmx but if you allow un-sanitized user input to be returned by your server like in his example app there are not many solutions that will come off any better off.
Conclusion: When a site uses HTMX, the attack surface of HTML injection is the same as any other SSR solution. It is possible to limit the risk of XSS by using a content security policy. Security is simple and old school as you just sanitize your inputs which all modern backend stacks now make easy. But it not possible to have all HTMX features and provide 100% security against injection (unless you sanitize all inputs and only link to your own server).
For example, sure you can allow htmx on your page to make requests to domains you don't control. This is the proverbial shooting yourself in the foot. If you are allowing this in your site, you have much deeper problems than htmx and need much bigger interventions than CSP.
Related
Hypermedia Systems
The book "Hypermedia Systems" by Carson Gross, Adam Stepinski, and Deniz Akşimşek, with a foreword by Mike Amundsen, introduces innovative web development concepts using htmx and Hyperview. It caters to web developers, individuals interested in web basics, and companies transitioning apps to mobile platforms. Available online and on Amazon.
I found a 1-click exploit in South Korea's biggest mobile chat app
A critical exploit in KakaoTalk allows attackers to run JavaScript in a WebView, potentially compromising user accounts by stealing access tokens. The exploit highlights the need to address security vulnerabilities in messaging apps.
Polyfill supply chain attack hits 100K+ sites
A supply chain attack on Polyfill JS affects 100,000+ websites, including JSTOR and Intuit. Malware redirects mobile users to a betting site. Users advised to switch to trusted alternatives like Fastly and Cloudflare.
If you're using Polyfill.io code on your site – remove it immediately
A Chinese organization acquired polyfill.io, infecting 100,000+ websites with malware. Security warnings urge removal of its JavaScript code. Google blocks ads on affected sites. CDN mirrors aim to reduce risks.
An Htmx Success Story
Discussion on transitioning from Django+React to Django+HTMX stack. Challenges with Django and React highlighted, solved with HTMX and AlpineJS. Improved simplicity, productivity, and compatibility with older devices. Transition driven by developer productivity.