Hello!
I am having an issue with HTMX 4 (Beta 4) where hx-csp does not seem to correctly use the fresh nonce from the new partial response from the server, and get instead the following error:
hx-csp.js:90 htmx: [hx-csp] blocked <form#form-login> — nonce mismatch (possible injection)
CSP Settings
SECURE_CSP = {
"default-src": [CSP.SELF],
"script-src": [CSP.SELF, CSP.NONCE, "'strict-dynamic'" ],
"img-src": [CSP.SELF, "data:"],
}
Partial Snippet
<c-form
x-data="form_login_data"
id="form-login"
class="self-center gap-0"
hx-disable:inherited="this, #form-login-submit, #username, #email, #password, #select-language, #select-theme"
@input="updateFormDisabledState"
hx-nonce="{{ csp_nonce }}"
hx-post="{% url "fe-login" %}"
hx-swap="none"
hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'
> (...)
</c-form>
I don't know if I'm being a dummy, or missing something but, according to the HTMX CSP Documentation which I quote:
The extension rewrites the response nonce to the page nonce so swapped-in elements pass subsequent nonce checks.
Before doing that rewrite, it scrubs any element that already carries the page nonce value from the raw response text.
In theory (and from what I can see in the response headers) each server response has a different nonce, just as the documentation says:
The server cannot know the page nonce — it only knows its own per-response nonce. So if the page nonce appears in a response, it was put there by an attacker, not the server. Scrubbing it first means the rewrite pass cannot accidentally promote attacker-controlled elements to trusted status.
I have also tried returning partials without hx-nonce when the request is an htmx request, however that results in a no-nonce error, which makes sense and is probably what should happen.
From what I gather, HTMX wanting to match the previous nonce to the next/fresh one isn't intended behavior, right? Or am I doing something wrong?
Regards and thanks in advance,
Dylan
Edit:
I also see in the hx-csp code that the following function compares the nonce to the page Nonce rather than the response Nonce...
function checkNonce(elt) {
if (!pageNonce) return false;
let eltNonce = getNonce(elt);
if (eltNonce !== pageNonce && stripHxAttributes(elt, eltNonce)) return false;
}
Hello!
I am having an issue with HTMX 4 (Beta 4) where
hx-cspdoes not seem to correctly use the fresh nonce from the new partial response from the server, and get instead the following error:hx-csp.js:90 htmx: [hx-csp] blocked <form#form-login> — nonce mismatch (possible injection)CSP Settings
Partial Snippet
I don't know if I'm being a dummy, or missing something but, according to the HTMX CSP Documentation which I quote:
In theory (and from what I can see in the response headers) each server response has a different nonce, just as the documentation says:
I have also tried returning partials without hx-nonce when the request is an htmx request, however that results in a no-nonce error, which makes sense and is probably what should happen.
From what I gather, HTMX wanting to match the previous nonce to the next/fresh one isn't intended behavior, right? Or am I doing something wrong?
Regards and thanks in advance,
Dylan
Edit:
I also see in the hx-csp code that the following function compares the nonce to the page Nonce rather than the response Nonce...