BastionCSP
BastionCSP: Content Security Policy nonce injection for Bastion web apps.
Generates a cryptographically random nonce per request, assigns it to the Conn under the key "csp_nonce", and emits the appropriate Content-Security-Policy header.
Typical usage in an endpoint pipeline:
conn
|> BastionCSP.protect()In templates, retrieve the nonce via:
let n = BastionCSP.nonce(conn)
"<script nonce=\"" ++ n ++ "\">...</script>"Default policy (strict): default-src 'self' script-src 'self' 'nonce-NONCE' style-src 'self' 'nonce-NONCE' img-src 'self' data: https: font-src 'self' connect-src 'self' wss: worker-src 'self' blob: frame-ancestors 'self' base-uri 'self' form-action 'self'
Functions
Generate a fresh nonce (16 random bytes, base64-encoded) and assign it to the Conn under the key "csp_nonce". Returns the updated Conn.
conn: BastionCSP.assign_nonce(conn)No-op: returns the Conn unchanged. Useful to explicitly mark that CSP is intentionally disabled for a route (e.g. during local development).
conn |> BastionCSP.disable()Retrieve the CSP nonce from the Conn assigns.
Returns Some(nonce_string) if assign_nonce has been called, None otherwise.
match BastionCSP.get_nonce(conn) do
Some(n) -> n
None -> ""
endReturn the nonce string, or an empty string if none has been assigned.
let n = BastionCSP.nonce(conn)Assign a fresh nonce and set the Content-Security-Policy header in one step. This is the primary entry point for most pipelines.
conn |> BastionCSP.protect()Assign a fresh nonce and set a customised Content-Security-Policy header. overrides is a List((String, String)) of directive pairs that replace the corresponding defaults.
conn
|> BastionCSP.protect_with_overrides(
Cons(("img-src", "'self'"), Nil))Assign a fresh nonce and set a Content-Security-Policy-Report-Only header, appending report-uri <report_uri> to the default policy.
conn |> BastionCSP.report_only(conn, "https://csp.example.com/report")Set the Content-Security-Policy response header using the nonce already assigned to the Conn. Call assign_nonce/1 first (or use protect/1).
conn
|> BastionCSP.assign_nonce()
|> BastionCSP.set_header()