feat(security): strict Content-Security-Policy and security headers - #42
Merged
Conversation
Harden the browser surface and make the zero-knowledge passphrase mode CSP-safe. - A per-request security-headers middleware sets a strict CSP: no third-party origins, `script-src 'self' 'nonce-…' 'wasm-unsafe-eval'`, `style-src 'self' 'unsafe-inline'`, `object-src 'none'`, `frame-ancestors 'none'`, etc. The `wasm-unsafe-eval` directive lets the vendored hash-wasm Argon2 module run, so the ZK passphrase decryption keeps working under CSP. Also nosniff, Referrer-Policy, X-Frame-Options: DENY and a restrictive Permissions-Policy. `/docs` /`/redoc` are exempt (Swagger needs inline + CDN). - Remove inline JS so the CSP can forbid it: the one inline (theme no-flash) script carries the request nonce, and all `onsubmit="confirm(…)"` handlers become `data-confirm` wired by a small vendored `confirm.js`. Verified in a real browser: the theme applies, delete confirmations work, and an Argon2-passphrase private item decrypts in-page — with zero CSP violations. Tests assert the CSP (wasm-unsafe-eval + per-request nonce matching the inline script) and the docs exemption. Full suite 215 passed; ruff + mypy(strict) green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Complete the minimal ZK stack hardening for ghostmon: a strict CSP that keeps the
in-browser Argon2 (zero-knowledge passphrase mode) working via
wasm-unsafe-eval,plus the usual security headers.
Changes
script-src 'self' 'nonce-…' 'wasm-unsafe-eval',style-src 'self' 'unsafe-inline',object-src 'none',frame-ancestors 'none', …), plusnosniff,Referrer-Policy,X-Frame-Options: DENY,Permissions-Policy./docs&/redocexempt (Swagger needs inline + CDN).
per-request nonce;
onsubmit="confirm(…)"handlers →data-confirm+ a smallvendored
confirm.js.Verification
Real browser (Playwright): theme applies, delete confirmations work, and an
Argon2-passphrase private item decrypts in-page — zero CSP violations. Tests
assert the CSP (wasm-unsafe-eval + per-request nonce matching the inline script) and
the docs exemption. Full suite 215 passed; ruff + mypy(strict) green.