Skip to content

docs: hx-nonce and CSP_STYLE_SRC_STRICT opt-ins require a framework release before they work in scaffolded projects #1778

@davidpoblador

Description

@davidpoblador

Summary

The two new opt-ins introduced by the htmx beta3 review (#1773 hx-nonce extension + #1774 CSP_STYLE_SRC_STRICT flag) are documented in vibetuner-docs/docs/development-guide.md, but a freshly scaffolded project on main today cannot use either of them yet:

  1. hx-nonce import fails to build. Scaffolded package.json pulls @alltuner/vibetuner@^10.9.0, which transitively resolves htmx.org@4.0.0-beta2. beta2 does not ship dist/ext/hx-nonce.js, so bun run build:js errors out:

    error: Could not resolve: "./node_modules/htmx.org/dist/ext/hx-nonce.js"
        at config.js:9:8
    
  2. CSP_STYLE_SRC_STRICT=true is silently ignored. Scaffolded pyproject.toml pulls vibetuner==10.10.0 from PyPI, which predates feat(security): add CSP_STYLE_SRC_STRICT to drop 'unsafe-inline' from style-src #1774. Pydantic settings' extra="ignore" means the env var is parsed but discarded; the CSP header keeps emitting style-src 'self' 'unsafe-inline' with no warning.

Both issues self-resolve once the next vibetuner release lands on PyPI / npm (release-please bump to 10.11.0). I confirmed end-to-end that both opt-ins work with the editable install pointing at main: strict CSP becomes style-src 'self' 'nonce-<request-nonce>', the bundle build succeeds, and the bundled bundle.js contains the hx-nonce extension code (htmx:security:strip, htmx:security:violation, nonce-mismatch identifiers all present).

Smoke test results (against main + local editable install)

  • 9 default pages exercised (/, /auth/login, /debug/, /debug/info, /debug/version, /debug/blocks, /debug/config, /debug/collections, /debug/users)
  • All return strict style-src 'self' 'nonce-...', zero 'unsafe-inline', zero inline style="..." attributes, every <style> and <script> carries the request nonce
  • bundle.js (~87KB) successfully imports hx-nonce.js and is served under strict CSP without violations
  • Framework template (user/profile.html.jinja:112) correctly stamps hx-nonce="{{ csp_nonce }}" on its single htmx-bearing button

Suggested fixes

Pick one or more, in priority order:

  1. Wait it out. Just merge the next release-please PR; the docs become accurate the moment 10.11.0 hits npm/PyPI. Add a "From version X" note in the development-guide.md sections so users on older versions know.
  2. Add a minimum-version footnote in the two opt-in subsections of development-guide.md (htmx Nonce Protection and Strict style-src) — something like "Requires @alltuner/vibetuner ≥ 10.11.0 and vibetuner ≥ 10.11.0".
  3. Fail-loud for unknown CSP_ env vars* (optional, defensive). Drop the extra="ignore" in SecurityHeadersSettings so a typo or future-future flag emits a startup warning. Not strictly necessary for this case but generally good practice for opt-in security flags.
  4. Verify post-release. When 10.11.0 lands, scaffold a fresh project against npm/PyPI (not the editable install) and confirm the doctor test passes without manual intervention.

Reproducer

# from clean main checkout
uv run --directory vibetuner-py vibetuner scaffold new ./.tmp/repro --defaults --template ./
cd vibetuner-py/.tmp/repro
echo "CSP_STYLE_SRC_STRICT=true" >> .env
sed -i '' 's|// Add your custom imports below:|&\nimport "./node_modules/htmx.org/dist/ext/hx-nonce.js";|' config.js
bun run build:js  # FAILS — htmx.org@4.0.0-beta2 has no hx-nonce.js

# even if you skip the JS step:
uv sync && uv run --frozen vibetuner run dev  # CSP_STYLE_SRC_STRICT silently ignored, style-src still has 'unsafe-inline'

Related

🤖 Filed via Claude Code from a post-merge smoke test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions