Hacker News new | ask | show | jobs
by mtlynch 720 days ago
The relevant thing here is that before, CSP would protect you even if you failed to sanitize an attacker-controlled input. Bringing in htmx allows the attacker to bypass CSP, and that hasn't been documented well before.

The htmx docs mention CSP in passing but don't explore the nuance that OP does.

1 comments

I think that's only true if your CSP has the word 'unsafe' or '*' in it. If it doesn't, it shouldn't allow inline code or things from domains that you didn't whitelist.

And that's not HTMX or CSP's fault.

>I think that's only true if your CSP has the word 'unsafe' or '*' in it.

No, that's the subtlety that a lot of people in the thread are missing. I wish OP did a better job of explaining the difference.

Imagine that you screw up and some part of your page assigns injects an attacker-controlled string without encoding properly:

So you have something like this:

    <div class="ugc">{{ user_message }}</div>
And the attacker can inject arbitrary HTML/JS, so they do this:

    <div class="ugc"><script>fetch('/account', { method: 'DELETE' })</script></div>
If you have CSP enabled with standard settings, the attack won't execute. CSP saves you even if you screwed up that badly.

The problem is that even if you keep the CSP settings secure and you add htmx into your app, the attacker can effectively achieve XSS because htmx's functionality is powerful enough that it's mostly equivalent to having arbitrary JS execution:

    <div class="ugc"><span hx-delete="/account" hx-trigger="load"></span></div>
So, without htmx, CSP protects you from mistakenly sanitizing input / encoding output, but with htmx, you lose a lot of the benefit of CSP.
Fair enough. It is a trade-off I guess.
Yeah, if HTMX is not protecting against injection of its own code, then it's absolutely at fault here. That's a huge problem.