htmx Security
Use this skill before shipping htmx features that render user content, accept rich HTML, add third-party scripts, change Content Security Policy, or expose new mutation endpoints.
Threat Model
htmx keeps rendering on the server, but unsafe HTML is still unsafe HTML. A fragment swap can insert scripts, event handlers, dangerous URLs, or htmx attributes that cause requests. Treat every fragment as executable browser surface unless it is escaped or sanitized.
Baseline Rules
- Escape user-supplied text by default.
- Sanitize rich HTML on the server with a strict allowlist.
- Strip or block
hx-*, data-hx-*, hx-on, inline event handlers, script, dangerous URLs, and style features that the product does not explicitly allow.
- Keep auth, authorization, and validation on the server.
- Use CSRF protection for same-origin mutations.
- Do not put secrets, privileged object IDs, or authorization decisions in HTML attributes.
- Keep htmx requests same-origin unless CORS, CSRF, cookies, and credentials are deliberately designed.
User Content
Choose one content policy:
| User content type |
Policy |
| Plain text |
Escape and render as text |
| Markdown |
Render through a sanitizer and allow only safe tags/attributes |
| Rich HTML |
Sanitize with a narrow allowlist and strip htmx/event/script capabilities |
| Trusted admin HTML |
Still sanitize unless the trust boundary is documented and access is tightly controlled |
Do not mark content safe merely because it was stored in the database earlier.
htmx-Specific Risks
- User-controlled
hx-get, hx-post, hx-put, hx-patch, hx-delete, or hx-trigger can create unintended requests.
- User-controlled
hx-on or inline handlers can execute JavaScript.
- User-controlled
hx-vals can smuggle unexpected parameters.
- Fragment responses can replace more of the page than intended if targets are broad.
- History caching can retain sensitive HTML on the client.
Use hx-history="false" on sensitive pages or containers that should not be stored in htmx history cache.
CSRF And Cookies
- Prefer the framework's standard CSRF mechanism.
- Configure htmx to send the CSRF header once in the base layout or startup script.
- Keep CSRF tokens out of logs and analytics.
- Use
Secure, HttpOnly, and SameSite cookie settings appropriate to the app.
- Avoid cross-site htmx mutations unless the app has a clear credential policy.
CDN And Script Loading
Prefer vendored static assets for reproducibility. If loading htmx or extensions from a CDN:
- pin the exact version;
- include Subresource Integrity where possible;
- set
crossorigin when required by SRI;
- document why CDN loading is acceptable for the app;
- monitor version changes deliberately rather than floating to latest.
Content Security Policy
Design CSP around the actual frontend stack:
- htmx can work with a strict CSP when inline scripts and unsafe eval are avoided.
- Inline event handlers,
hx-on, Alpine default builds, and _hyperscript can require looser policies unless replaced with CSP-compatible patterns.
- Start with report-only mode for existing apps, then tighten.
- Include reporting endpoints only when someone reviews reports.
- Test swapped fragments under the final CSP, not just the initial page load.
Review Checklist
- Are all mutation endpoints protected by auth, authorization, and CSRF?
- Does every endpoint re-check permissions server-side?
- Are user values escaped in fragments and full pages?
- Is any rich content sanitized with an allowlist?
- Can user content inject
hx-*, hx-on, event handlers, scripts, or dangerous URLs?
- Are sensitive fragments excluded from htmx history cache?
- Are third-party scripts pinned and integrity-checked?
- Does CSP match Alpine,
_hyperscript, and htmx usage?
- Do tests cover both htmx and non-htmx paths?
Testing Ideas
- Submit text containing HTML tags and confirm it renders as text.
- Submit sanitized rich content with attempted event handlers and htmx attributes.
- Attempt unauthorized htmx mutations directly with forged headers.
- Verify login redirects do not get swapped into small targets.
- Run browser checks with CSP enabled and inspect violations.
Avoid
- Do not rely on htmx headers as proof of trust.
- Do not trust hidden inputs,
hx-vals, or client-side state for authorization.
- Do not allow user-authored htmx attributes in normal rich content.
- Do not loosen CSP globally to fix one component without documenting the tradeoff.
- Do not expose JSON or HTML endpoints with different authorization assumptions.
Source: hashgraph-online/awesome-codex-plugins → plugins/LVTD-LLC/skills/skills/htmx-security/SKILL.md
1---2name: htmx-security3description: Review and harden security for htmx and server-driven web apps. Use when handling user-supplied HTML, escaping or sanitizing fragments, adding CSP, evaluating XSS risk, configuring CSRF or cookies, loading htmx from a CDN, using SRI hashes, accepting hx-* attributes from content, or reviewing htmx request headers and history caching.4---567# htmx Security89Use this skill before shipping htmx features that render user content, accept rich HTML, add third-party scripts, change Content Security Policy, or expose new mutation endpoints.1011## Threat Model1213htmx keeps rendering on the server, but unsafe HTML is still unsafe HTML. A fragment swap can insert scripts, event handlers, dangerous URLs, or htmx attributes that cause requests. Treat every fragment as executable browser surface unless it is escaped or sanitized.1415## Baseline Rules1617- Escape user-supplied text by default.18- Sanitize rich HTML on the server with a strict allowlist.19- Strip or block `hx-*`, `data-hx-*`, `hx-on`, inline event handlers, `script`, dangerous URLs, and style features that the product does not explicitly allow.20- Keep auth, authorization, and validation on the server.21- Use CSRF protection for same-origin mutations.22- Do not put secrets, privileged object IDs, or authorization decisions in HTML attributes.23- Keep htmx requests same-origin unless CORS, CSRF, cookies, and credentials are deliberately designed.2425## User Content2627Choose one content policy:2829| User content type | Policy |30| --- | --- |31| Plain text | Escape and render as text |32| Markdown | Render through a sanitizer and allow only safe tags/attributes |33| Rich HTML | Sanitize with a narrow allowlist and strip htmx/event/script capabilities |34| Trusted admin HTML | Still sanitize unless the trust boundary is documented and access is tightly controlled |3536Do not mark content safe merely because it was stored in the database earlier.3738## htmx-Specific Risks3940- User-controlled `hx-get`, `hx-post`, `hx-put`, `hx-patch`, `hx-delete`, or `hx-trigger` can create unintended requests.41- User-controlled `hx-on` or inline handlers can execute JavaScript.42- User-controlled `hx-vals` can smuggle unexpected parameters.43- Fragment responses can replace more of the page than intended if targets are broad.44- History caching can retain sensitive HTML on the client.4546Use `hx-history="false"` on sensitive pages or containers that should not be stored in htmx history cache.4748## CSRF And Cookies4950- Prefer the framework's standard CSRF mechanism.51- Configure htmx to send the CSRF header once in the base layout or startup script.52- Keep CSRF tokens out of logs and analytics.53- Use `Secure`, `HttpOnly`, and `SameSite` cookie settings appropriate to the app.54- Avoid cross-site htmx mutations unless the app has a clear credential policy.5556## CDN And Script Loading5758Prefer vendored static assets for reproducibility. If loading htmx or extensions from a CDN:5960- pin the exact version;61- include Subresource Integrity where possible;62- set `crossorigin` when required by SRI;63- document why CDN loading is acceptable for the app;64- monitor version changes deliberately rather than floating to latest.6566## Content Security Policy6768Design CSP around the actual frontend stack:6970- htmx can work with a strict CSP when inline scripts and unsafe eval are avoided.71- Inline event handlers, `hx-on`, Alpine default builds, and `_hyperscript` can require looser policies unless replaced with CSP-compatible patterns.72- Start with report-only mode for existing apps, then tighten.73- Include reporting endpoints only when someone reviews reports.74- Test swapped fragments under the final CSP, not just the initial page load.7576## Review Checklist7778- Are all mutation endpoints protected by auth, authorization, and CSRF?79- Does every endpoint re-check permissions server-side?80- Are user values escaped in fragments and full pages?81- Is any rich content sanitized with an allowlist?82- Can user content inject `hx-*`, `hx-on`, event handlers, scripts, or dangerous URLs?83- Are sensitive fragments excluded from htmx history cache?84- Are third-party scripts pinned and integrity-checked?85- Does CSP match Alpine, `_hyperscript`, and htmx usage?86- Do tests cover both htmx and non-htmx paths?8788## Testing Ideas8990- Submit text containing HTML tags and confirm it renders as text.91- Submit sanitized rich content with attempted event handlers and htmx attributes.92- Attempt unauthorized htmx mutations directly with forged headers.93- Verify login redirects do not get swapped into small targets.94- Run browser checks with CSP enabled and inspect violations.9596## Avoid9798- Do not rely on htmx headers as proof of trust.99- Do not trust hidden inputs, `hx-vals`, or client-side state for authorization.100- Do not allow user-authored htmx attributes in normal rich content.101- Do not loosen CSP globally to fix one component without documenting the tradeoff.102- Do not expose JSON or HTML endpoints with different authorization assumptions.103104---105106**Source:** [`hashgraph-online/awesome-codex-plugins`](https://github.com/hashgraph-online/awesome-codex-plugins) → `plugins/LVTD-LLC/skills/skills/htmx-security/SKILL.md`