Readit News logoReadit News
mtlynch · a year ago
There are some good points here, but I think the author neglects to dig deeper and explain how you can mitigate some of these risks with htmx settings.

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.

bastawhiz · a year ago
> you have to screw up a lot more to give the attacker complete control over the HTML.

Isn't this just a XSS vulnerability?

mtlynch · a year ago
What I mean is that imagine you have HTML like this:

    <div hx-disable><img src="foo.jpg"></div>
You might screw up and give the attacker a way to control the src attribute like:

    <div hx-disable><img src="//evil.com/bad.jpg"></div>
So, maybe unintentional behavior but still no xss.

And if you let the attacker inject double quotes, then they can escape the attribute and do something like this:

    <div hx-disable><img src="foo" hx-delete="/account" hx-trigger="load"></div>
In this case, htmx would still prevent the xss because hx-disable causes htmx to ignore the hx-delete attribute in the child element.

But if we assume the server fails to encode angle brackets too, then the attacker wins because they can terminate the hx-disable, as described in the post.

    <div hx-disable><img src="foo"></div><span hx-delete="/account" hx-trigger="load"></span>
But they're different levels of screwup. Accidentally letting the attacker control the value of the attribute is one level, letting them inject extra attributes is another level, and letting them inject extra HTML elements is another level.

Granted, if you're screwing up output encoding, you're likely going to grant the attacker the ability to inject elements at the same time that you allow them to inject attributes, but the defender has a bit more protection if they disallow or encode angle brackets in user input.

stouset · a year ago
If you allow random users to write arbitrary unsanitized HTML into other users’ pages, you have already lost, htmx or otherwise.
bakugo · a year ago
> If you allow random users to write arbitrary unsanitized HTML into other users’ pages, you have already lost

Not really. The whole point of CSP is that, even if someone manages to inject arbitrary HTML into your page due to a bug or oversight, you can prevent injected scripts from running entirely, severely limiting what an attacker can do.

I'm surprised at the amount of comments on this post that seem to be completely clueless about CSP.

stouset · a year ago
CSP is a backstop that—when configured properly and used alongside restraint in how you script—can minimize some of the worst consequences of injection.

It doesn’t wash your hands clean of the responsibility to restrict what kinds of content users can inject into served pages.

elmigranto · a year ago
> if someone manages to inject arbitrary HTML

If they can, why wouldn’t it be inline <script>?

Akronymus · a year ago
serving html with string concatenation is just like creating sql statements with string concat.

At least thats how I see it. Ideally you'd use something similar to prepared statements, just for html templates.

whazor · a year ago
Besides whether it is a real security risk, this is useful information if you have to work with a security department. In particular, there are corporate environments where certain CSP settings would require approval or are simply not possible.
stouset · a year ago
An article focused on "htmx requires more CSP exceptions than you might be comfortable with" would be great. This is not that article.
Ayesh · a year ago
HTMX always assumes that the incoming HTML is properly sanitized. If it isn't, the application is already vulnerable.

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.

ackers · a year ago
I don't see the point of this article, it's just common sense. If you plan which parts of the DOM are replaced using HTMX, never trust user input. You'll be fine. I use Golang with HTMX and it's amazingly productive.
ramon156 · a year ago
Not everyone's as knowledged, hence information should be shared
qsort · a year ago
I think the point is that htmx is in no way special. It's the same old category of vulnerability. It's why we have execvpe. It's why we have mysql_real_escape_string_no_really_we_mean_it_this_time().

I remember a similar point being made about LLM output. Now, I'm anything but a LLM fanboy, but if you pipe unknown text into a system interface that's squarely on you.

esjeon · a year ago
I mean that's the point. Reminding people of possible dangers is one very important security mission.
pessimizer · a year ago
I think the point being made that you're replying to is that it has nothing to do with htmx. It isn't htmx that's not playing well with content security policy.
iamkonstantin · a year ago
it’s unclear what point the post is trying to make. The outlined behaviour is not specific to HTMx per-se. These are security considerations for all server rendered pages.

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

https://htmx.org/essays/web-security-basics-with-htmx/

the8472 · a year ago
The point of CSP is to lock down your site so that any content (buggy or malicious) can't do damage.

This requires templating engines to separate styles, scripts and event handlers from the html.

> These are security considerations for all server rendered pages.

That's not true. With the right CSP and sandbox rules content can be made inert without sanitizing.

Sanitizing is still a good idea of course, but a rendering engine that is designed with CSP in mind will provide more layers of defense.

iamkonstantin · a year ago
What is a rendering engine with CSP in mind?

The server can, at best, set the correct CSP header. It’s a validation performed entirely in the browser. Even the best intended rendering from the server can’t prevent CSP violation attempts when the client is executing some kind of script. That’s why even frameworks like Vue and React need a correctly configured CSP.

andybak · a year ago
> These are security considerations for all server rendered pages

Well - "server rendered" to my ears primarily means plain html generated on the server using Perl, Python, PHP, CGI or whatever. I presume you mean "server rendered with some client-side code to handle injecting into the current DOM.

Am I just too old-school or does using "server rendered" to mean fairly specific things seem strange?

isodev · a year ago
You're correct. Server-rendered pages may also have some client-side interactivity using, for example, JavaScript/AJAX.... It doesn't need to be a fancy framework like htmx, but one needs to be mindful about user input and remote content either way. The same "techniques" for securing a web page remain in effect.
vidarh · a year ago
It doesn't matter how it's rendered or where it's rendered. If it lets user A put unescaped/filtered/sanitised data on user B's pages, it's a security issue, no matter how the page was rendered. It's one that can be mitigated in various ways, but it's important to take into account.

Deleted Comment

latent22 · a year ago
https://github.com/MichaelWest22/htmx-extensions/tree/main/s...

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.

theandrewbailey · a year ago
I was under the impression that most (if not all) browser JS frameworks need hilariously bad CSPs like this, particularly for dynamic styling. Am I mistaken?

I'm surprised that CSPs with unsafe-inline aren't treated with the same hate that table based layouts get. They are really bad.

hannob · a year ago
I feel 2/3 of the comments here are missing the point.

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.