$ Not a claim -- a live check
Every panel below reads real state from the running backend: actual response headers off a live request, an actual rate limiter tripping in real time, and this project's actual, currently-passing test count. Nothing here is a screenshot or a hardcoded number.
Live security headers self-check
A fresh GET /api/health request, made by your browser just now, checked against backend/app/security_headers.py.
Live rate-limit demo
GET /api/security-demo/rate-limit-ping is guarded by its own real limiter capped at 5 requests / 15s (separate from the budgets RSA keygen, classical attacks, and Shor's algorithm actually use elsewhere on this site). Fire 8 requests back-to-back and watch it trip.
Live timing side-channel measurement
Measures actual wall-clock time, on this server, right now: how long _pkcs7_unpad and oaep_decode each take to reject a ciphertext, split by why it was rejected. This is the actual mechanism behind a Bleichenbacher-style padding-oracle attack -- an attacker who can only observe response time, never the plaintext, can still learn where validation failed.
Dependency & verification status
Kept honest rather than aspirational -- what's automated in CI, what's been checked by hand, and what still isn't automated.
ruffandmypyrun in CI on every push/PR (.github/workflows/ci.yml).pip-auditruns in CI against bothrequirements.txtandrequirements-dev.txt.- Known gap: the frontend's
npm auditis not wired into CI yet -- a real high-severityreact-routerCSRF advisory was caught and fixed manually during this project's development, but a regression wouldn't be caught automatically today. Documented here rather than left as a silent gap.
OWASP Top 10 (2021) mapping
Where each category applies to this project, and what addresses it (or why it's out of scope for a stateless, keyless-auth demo site).
| Category | This project |
|---|---|
| A01: Broken Access Control | No auth/authorization model exists -- every endpoint is public and read/compute-only. No user data, no privileged action, so no access-control boundary to break. |
| A02: Cryptographic Failures | The entire site. Textbook RSA is deliberately unpadded and malleable -- see the Malleability & Tampering Lab and SECURITY.md’s "known limitations" for the full, named list. |
| A03: Injection | No shell execution, no SQL, no template injection anywhere in the codebase (verified by grep for eval/exec/subprocess/os.system as part of this review). All inputs are Pydantic-validated before touching business logic. |
| A04: Insecure Design | The RSA weaknesses are an intentional teaching design, not an accident -- explicitly disclosed rather than hidden. Rate limiting and security headers exist so the demo site itself is not trivially abusable. |
| A05: Security Misconfiguration | CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy, HSTS, and no-store caching are set explicitly per response (backend/app/security_headers.py), checked live above rather than assumed. |
| A06: Vulnerable & Outdated Components | pip-audit runs in CI; npm audit is checked manually (0 known CVEs currently) -- the gap in CI automation is disclosed above, not hidden. |
| A07: Identification & Authentication Failures | No authentication exists on this site -- out of scope by design (nothing here is a real account or session). |
| A08: Software & Data Integrity Failures | Directly demonstrated, not just mitigated: the malleability and block-substitution attacks on this page ARE integrity failures, shown live against real code. |
| A09: Security Logging & Monitoring Failures | Errors return clean, non-leaking JSON (backend/app/errors.py) but there is no structured audit log -- reasonable for a stateless educational demo with no accounts or sensitive actions to audit. |
| A10: Server-Side Request Forgery | No endpoint accepts or fetches a user-supplied URL anywhere in the API surface, so there is no SSRF-shaped input to exploit. |