The checklist
None of this is clever and all of it is forgettable, which is why it belongs on a list that somebody runs before a launch and once a quarter after it.
| Area | What good looks like |
|---|---|
| TLS | https everywhere, http redirects, HSTS with a long max-age and subdomains |
| Headers | CSP without unsafe-inline, nosniff, a referrer policy, frame-ancestors none |
| Cookies | HttpOnly, Secure, SameSite, a sensible Max-Age, scoped to a path |
| CORS | an allowlist, never a reflected origin, no wildcard with credentials |
| Errors | a generic message to the user, the detail in the log, never a stack trace |
| Admin | not on the public origin, behind a second factor, logged |
| Defaults | no default credentials, no sample app, no directory listing, no .git served |
The leak that is just a default
Turn the framework's production mode on — it is what disables the detailed error page — remove the version headers, and check that the deployment does not serve dotfiles. These take minutes and they remove the reconnaissance step entirely.
/.git/config # the whole source history, if the directory is served
/.env # the whole configuration
/server-status, /actuator # internals, sometimes with credentials
X-Powered-By: Express # the version to look up
/api/docs # every endpoint, helpfully
a stack trace on a 500 # file paths, library versions, sometimes SQL
Errors, and what the user is told
The request id is the whole trick: the user can quote it to support, and support can find the detail without the user ever seeing it. It also stops the temptation to put the real error in the response "just for now".
// to the user
{ "error": "Something went wrong", "requestId": "req_8f3d21" }
// to the log
{ event: "unhandled", requestId: "req_8f3d21", stack, query, userId }
And the things that are not headers
- Backups — encrypted, restorable, and actually restored once. An untested backup is a hope.
- Access — who can reach production, with what, and what happens when they leave.
- Dependencies — the weekly upgrade from that lesson, running.
- A way to be told. A
security.txtfile, a monitored address, and an answer within a day. Most vulnerabilities are reported by someone being helpful; make it easy.