v1.13.2 — Phishing-resistant authentication enforcement
SPARC v1.13.2 — Phishing-resistant authentication enforcement
Builds on the phishing-resistant MFA foundation shipped in v1.13.0 (FIDO2) and
v1.13.1 (PIV/CAC). This release adds the enforcement layer — the controls an
operator uses to require strong authentication org-wide — plus a defense-in-depth
filter for which smart-card certificates SPARC will accept, and closes the last
raw-XML upload path.
All new controls are off by default: existing deployments upgrade with no
behavior change and no configuration required.
✨ Highlights
Mandatory FIDO2 enrollment gate (#802)
A single variable, SPARC_REQUIRE_FIDO2, both enables FIDO2 and sets who
must enroll a security key before they can use the app:
| Value | Effect |
|---|---|
off (default) |
FIDO2 opt-in only (unchanged — still enabled explicitly with SPARC_FIDO2_ENABLED=true) |
local |
Local-password users must enroll a key |
all |
Every interactive user must enroll a key |
Users without a registered key are redirected to the security-key management page
until they enroll. The break-glass admin and service accounts are exempt.
Require phishing-resistant sign-in (#805)
SPARC_REQUIRE_AUTH_METHODS is a comma-separated allowlist of the login methods
your organization accepts — e.g. oidc,piv. Anyone who authenticates by a method
not on the list is signed out and returned to the login page with a clear message.
Enforced in the app, so it works on a single-listener mTLS gateway without a
dedicated PIV host. Break-glass admin and service accounts are exempt.
Tokens: oidc (= openid_connect/sso), piv, webauthn/fido2, github,
gitlab, ldap, local. Empty (default) = no restriction.
Optional PIV/CAC certificate issuer & policy filter (#804)
Defense-in-depth on the PIV/CAC path: accept a gateway-forwarded client
certificate only if it comes from a configured issuer and/or carries a configured
certificate-policy OID.
| Variable | Meaning |
|---|---|
SPARC_PIV_ACCEPTED_ISSUERS |
CSV; case-insensitive substring match against the cert issuer DN |
SPARC_PIV_ACCEPTED_POLICY_OIDS |
CSV of certificate-policy OIDs (parsed from the cert via ASN.1) |
Both empty (default) → accept whatever the mTLS gateway validated (no change for
existing v1.13.1 PIV deployments). When set, a non-matching certificate is rejected
fail-closed and audited as a login failure; when both are set, a cert must
satisfy both. Trust of which CA to accept still lives at the gateway — this adds
a second, narrower allowlist in the app.
🔒 Security hardening
- ODP importer now parses XML through the hardened
XmlSecuritywrapper (SI-10).
This was the last file-upload path still on raw Nokogiri; it is now protected
against XXE / external-entity substitution and network fetches (.nonet),
consistent with every other XML ingestion path.
🧰 CI & test hygiene
- Ruff lint gate added for the Python test suites (#763, #801) + authentication docs.
- Gate on security-finding review-date freshness (#778, #798).
- Cleared database test-credential secret-scan false positives and fixed the
gitleaks config (#799). - CI/test-hygiene straggler cleanup (#747, #753, #788, #797).
⬆️ Upgrade notes
No action required — every new control defaults to off. To adopt them:
- Require security keys: set
SPARC_REQUIRE_FIDO2=localorall. - Require OIDC/PIV only: set
SPARC_REQUIRE_AUTH_METHODS=oidc,piv. - Restrict accepted PIV issuers/policies: set
SPARC_PIV_ACCEPTED_ISSUERSand/or
SPARC_PIV_ACCEPTED_POLICY_OIDS.
Operator setup for all three is documented in the Security Keys user guide,
which the in-app Help Center renders directly. See also docs/AUTHENTICATION.md
and docs/ENVIRONMENT_VARIABLES.md.
✅ Verification
Full tests/api (363 passed) and authenticated Playwright ui-smoke (226 passed,
including the FIDO2 enroll→passwordless ceremony) run green against the production
UBI9 image.
Full changelog: v1.13.1...v1.13.2