Lion Cipher Lab

Set secure defaults for a Node.js Express app with Helmet, header by header, measured

Why it matters

A fresh Express app ships with almost no browser-side protection. It announces itself with X-Powered-By: Express and sends none of the security headers that tell a browser to force HTTPS, refuse to be framed, stop guessing file types, or refuse injected scripts. Helmet is the standard one-line fix in the Node.js world, and both the Express project and OWASP point to it. But one line is where most teams stop, and that is where the trouble starts. Helmet's default Content-Security-Policy quietly breaks inline scripts and CDN scripts, so a developer under deadline pressure adds 'unsafe-inline'…

What you'll learn

Steps in this lab

  1. What you are building, and the words you need
  2. Install Node.js, then Express and Helmet at pinned versions
  3. Write the app: one file, three modes, two deliberate bugs
  4. Write the measuring tool: a header dump with a CSP check
  5. BEFORE: measure plain Express
  6. AFTER app.use(helmet()): read all 12 headers, one at a time
  7. The default CSP breaks the page: read the proof
  8. Fix the CSP properly: a per-request nonce and an explicit host
  9. Tune HSTS, and know when it does nothing
  10. Turn one header off on purpose, and leave X-XSS-Protection at 0
  11. X-Powered-By: app.disable versus Helmet, and why order matters
  12. trust proxy: make Express tell the truth about HTTPS behind a proxy
  13. Lock it in: a header test that fails CI when a header regresses
  14. Honest negatives: measure what headers do not fix
  15. What a reviewer checks, and cleaning up

Open the full interactive lab →