contracts.rules_chirpui_csp

Page actions AI-ready formats and sharing
Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

chirp-ui CSP contract check — the effective CSP must keep Alpine alive (#233).

chirp-ui drives its shell with Alpine: components evaluate expressions as JS (needsscript-src 'unsafe-eval') and toggle visibility via…

chirp-ui CSP contract check — the effective CSP must keep Alpine alive (#233).

chirp-ui drives its shell with Alpine: components evaluate expressions as JS (needsscript-src 'unsafe-eval') and toggle visibility via inline style="display:none"attributes that cannot be nonced (needs style-src 'unsafe-inline'). If the effective Content-Security-Policy forbids either, the entire interactive shell (collapse, dropdowns, theme toggle, command palette, modals) silently dies in the browser — and because CORS masks cross-origin script errors, there is no console error. That invisible failure is the worst class, so this rule fails loud atapp.check()time instead.

As of #233use_chirp_ui(app) owns this: it flips csp_nonce_enabled=True, which makes the compiler wireCSPNonceMiddleware with 'unsafe-eval'+ style-src 'unsafe-inline'automatically — so a stock chirp-ui app passes this check with no hand-written CSP. The rule exists to catch an app that pins its own conflicting static CSP (e.g. aSecurityHeadersMiddlewarewhose script-src drops inline/'unsafe-eval'and there is no nonce mechanism, or whosestyle-srcforbids inline style).

This rule runs only when chirp-ui is active (extras["chirpui_components"] is set byuse_chirp_uiat freeze). It is a no-op for non-chirp-ui apps so they are unaffected.

Severity is env-aware, mirroringrules_security_stack / rules_csp_nonce: ERROR in production, WARNING in staging, silent in development (the default) so dev apps and shipped examples stay clean.

The rule stays silent when:

  • chirp-ui is not active, or
  • a per-request nonce mechanism is active AND its style-src permits inline (the auto-wired path — everything Alpine needs is granted), or
  • a static CSP is in force that already permits both inline script ('unsafe-inline' or 'unsafe-eval'for the eval surface) and inline style.

Detection follows the sibling rules: middleware is matched by class name (type(mw).__name__) so this layer never imports middleware classes. The @alpinejs/csp build (alpine_csp=True) avoids evaland the inline bootstrap, but chirp-ui's shipped components still emit inline@click/ x-show/:class and the modal x-datafactory call, so it is not treated as exempt here — chirp-ui needs the standard build's relaxations.

contracts.rules_chirpui_csp

Name Type Default Description
type
qualified_name
element_type
description
source_file
line_number
is_autodoc
autodoc_element
_autodoc_template
_autodoc_url_path
_autodoc_page_type
title
doc_content_hash

Symbols on this page

_style_src_directive
function
def _style_src_directive(csp: str) -> str | None

Return thestyle-srcdirective value from a CSP string, or None.

Falls back todefault-src per the CSP spec when style-srcis absent.

Parameters

Name Type Default Description
csp str
_style_forbids_inline
function
def _style_forbids_inline(csp: str) -> bool

True when the effective style-src forbids inlinestyle=attributes.

A CSP forbids inline style when astyle-src (or fallback default-src) is present and does not list'unsafe-inline'. Alpine's x-showwrites inline style attributes that cannot be nonced, so this is fatal for chirp-ui.

Parameters

Name Type Default Description
csp str
_script_allows_alpine
function
def _script_allows_alpine(csp: str) -> bool

True when the script-src permits Alpine's inline bootstrap + eval.

Alpine needs inline script execution: either'unsafe-inline'(covers the bootstrap) or, under a nonce policy, the bootstrap is nonced — but it still needs'unsafe-eval'for expression evaluation. This helper answers "does a static CSP grant what Alpine needs without a nonce mechanism", so it requires'unsafe-inline' (un-nonced inline) AND 'unsafe-eval'.

Parameters

Name Type Default Description
csp str
_static_csp
function
def _static_csp(middleware_list: list[Any], config: Any) -> str | None

Resolve the static CSP string the app will actually send, or None.

Mirrorsrules_csp_nonce._effective_csp: an explicit SecurityHeadersMiddlewareconfig wins; otherwise the app-level content_security_policy fallback. The dynamic CSPNonceMiddlewareCSP is detected separately (it is always nonce-bearing + Alpine-aware by construction once chirp-ui flips the flag).

Parameters

Name Type Default Description
middleware_list list[Any]
config Any
check_chirpui_csp
function
def check_chirpui_csp(router: Router, config: Any, middleware_list: list[Any], extras: dict[str, Any] | None = None) -> list[ContractIssue]

Flag a chirp-ui app whose effective CSP would kill Alpine.

No-op unless chirp-ui is active (extras["chirpui_components"]set by use_chirp_ui). When active, validates the EFFECTIVE CSP the app will send:

  • script-src must allow Alpine's inline bootstrap + eval (via a nonce mechanism — auto-wired bycsp_nonce_enabled— or static 'unsafe-inline' + 'unsafe-eval');
  • style-src must allow inline style (Alpinex-showis un-nonceable).

Severity is env-aware (production ERROR, staging WARNING, development silent), mirroringrules_security_stack / rules_csp_nonce.

Parameters

Name Type Default Description
router Router
config Any
middleware_list list[Any]
extras dict[str, Any] | None None

View source · /home/runner/work/chirp/chirp/site/../src/chirp/contracts/rules_chirpui_csp.py:1