Skip to content

Security boundary types

Stability

Classifications for this surface are recorded in STABILITY.md. Package maturity (Beta/Alpha) is separate from API level (beta / experimental / internal / deferred).

Status: Accepted

Secret, TrustedHtml, and SafeUrl make security-sensitive intent visible to typing, rendering, diagnostics, and review.

from hedron import SafeUrl, Secret, TrustedHtml, UrlPurpose

token = Secret("deployment-token")
profile = SafeUrl.parse("/users/42", purpose=UrlPurpose.NAVIGATION)
body = TrustedHtml.reviewed(sanitized_html, source="application-sanitizer:v1")

Secret[T]

Secret(value) stores a typed sensitive value. When used in Hedron/Pydantic models as Secret[T], the inner value is validated against T (for example Secret[str] rejects an int). Its string conversion, representation, serialization, examples, diagnostics, traces, identities, and Explorer display are redacted. reveal() is the explicit application-only access operation; Hedron never reveals a secret implicitly to props, markup, URLs, cache-key text, logs, or browser metadata.

TrustedHtml

TrustedHtml.reviewed(value, *, source) creates an immutable raw-markup value at an explicit trust boundary. source is non-secret provenance for audit and diagnostics. The direct constructor is not public.

TrustedHtml.nh3(value, *, tags=None) sanitizes HTML with nh3 and records source as nh3:<version>. Requires the optional dependency:

pip install "hedron[sanitize]>=0.20.0,<0.21"
# or
pip install "hedron[markdown]>=0.20.0,<0.21"

Missing nh3 raises HED-SEC-0020 with that remediation. Integrations with supported sanitizers may provide equivalent named constructors that record a policy/version.

Only the dedicated hedron.html.raw(...) primitive accepts TrustedHtml. Wrapping a value does not sanitize it (except via TrustedHtml.nh3), weaken Content Security Policy, permit unregistered scripts/assets, or authorize its source. Ordinary strings always render as escaped text.

SafeUrl and UrlPurpose

SafeUrl.parse(value, *, purpose, allow_external=False) validates and normalizes a URL for one of the initial purposes: NAVIGATION, ASSET, FORM_ACTION, or REDIRECT. Relative same-origin URLs are the default. HTTP(S) external URLs require allow_external=True; mailto and tel are allowed only for an explicitly supported navigation context. Dangerous, ambiguous, credential-bearing, control-character, Unicode format/bidi/ZWSP/BOM-smuggled, or policy-incompatible schemes fail validation (HED-SEC-0001).

URL-bearing HTML attributes—including href, src, action, srcset, ping, and HTMX URL attrs such as hx-get / hx-push-url / hx-replace-url—require SafeUrl (or a validated srcset string whose candidates pass SafeUrl checks). Local HTMX path strings starting with / may be coerced at construction for HTMX attrs.

A SafeUrl remains subject to the final rendering or redirect context policy. Application helpers redirect_local and redirect_external enforce the same local-vs-external split; redirect_external is disabled unless the security policy sets allow_external_redirects=True.

SecurityPolicy and SecurityProfile

FastAPI apps select a named profile ("development" | "standard" | "strict") or pass an explicit SecurityPolicy to Hedron(security=...). Profiles are frozen dataclasses — mutate by constructing a new policy, not by assigning fields.

Field Type Default (standard) Notes
profile SecurityProfile STANDARD Named preset used to build the policy
version int 1 Policy schema version
csrf_enabled bool True Validate CSRF on unsafe methods
csrf_cookie_name str "hedron_csrf" Cookie set on safe GETs
csrf_header_name str "X-CSRF-Token" Preferred header for HTMX / fetch
csrf_form_field str "csrf_token" Hidden form field name
private_authenticated_cache bool True Adds Cache-Control: private, no-store when authenticated
security_headers bool True Emit XFO / CTO / Referrer-Policy / CSP when set
content_security_policy str | None standard CSP string None in development; stricter in strict
frame_options str "DENY" X-Frame-Options
content_type_options str "nosniff" X-Content-Type-Options
referrer_policy str "no-referrer" Referrer-Policy
explorer_enabled bool False Development profile may enable Explorer
allow_external_redirects bool False Required for redirect_external
findings tuple[str, …] profile notes Advisory strings for diagnostics / check
Profile CSRF CSP Explorer External redirects
development on none may mount off
standard on default-src self (+ limited inline style) off off
strict on tighter CSP, frame-ancestors 'none' off off
from hedron import Hedron
from hedron.security.policy import SecurityPolicy

app = Hedron(title="App", security="standard", session_secret="replace-in-production")
# or:
policy = SecurityPolicy.from_name("strict")
app = Hedron(title="App", security=policy, session_secret="replace-in-production")

CSRF cookie/header/form field names on SecurityPolicy are in the small stable API tier — see STABILITY.md. Full guide: Security.

csrf_token_for_request

Public FastAPI helper (re-exported from hedron and hedron.security) that returns the CSRF token for the current request under the app’s SecurityPolicy. Use it to seed hidden form fields or headers after a safe GET — see Minimal form POST.

from hedron import csrf_token_for_request

token = csrf_token_for_request(request, request.app.state.hedron_security)

Stability and errors

These values are immutable and safe to compare, but their representations never expose secret content.

Errors

Situation Code / behavior What to do
Invalid / dangerous URL HED-SEC-0001 (and related) Use SafeUrl.parse with the correct UrlPurpose; avoid javascript: and credentialed URLs
URL purpose mismatch for attribute HED-SEC-0006 Match purpose to the attribute (NAVIGATION, ASSET, FORM_ACTION, REDIRECT)
Missing nh3 for TrustedHtml.nh3 HED-SEC-0020 pip install "hedron[sanitize]>=0.20.0,<0.21" (or [markdown])
Secret leaked via str/repr Redacted Call reveal() only in trusted application code
html.raw(...) without TrustedHtml Rejected Wrap reviewed markup with TrustedHtml.reviewed / .nh3
External redirect without policy Rejected Set allow_external_redirects=True on an explicit SecurityPolicy

Adding a URL purpose or trusted constructor is a public API change. See Security guide and Error codes.