You can have perfect code and still leak everything through bad configuration. These are the three classic holes.
1 · Secrets management
"Secrets" = API keys, database passwords, encryption keys, JWT signing keys. The one unforgivable mistake is committing them to source control.
- Source history
A hardcoded secret is visible to readers of the repository and remains in previous commits.
- Secret delivery
Use an appropriate secret manager or deployment mechanism. Environment variables still require access and logging controls.
- Rotate
Revoke the leaked credential and issue a replacement. Removing the old text is not revocation.
Once a secret leaks, rotate it. Removing its current source line does not erase history.
How to read this model
A versioned document archive beside a separate key vault. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
2 · Debug mode in production
In development you log everything: stack traces, full SQL queries, database config, request bodies. That's useful locally: and dangerous if it ships.
| Log level | Shows | Where |
|---|---|---|
debug |
stack traces, SQL, config, sensitive data | local only |
info |
normal operational events | staging & production |
- Diagnostic detail
Debug logs can expose SQL, stack traces, or sensitive values when instrumentation is careless.
- Production events
Choose useful operational events and deliberate verbosity for production.
- Redact and restrict
Avoid logging secrets and private data, sanitize unsafe content, and restrict access and retention.
Log level alone is not a secrecy guarantee. Keep sensitive values out at every level.
How to read this model
A recorder with a filtered output gate. The object is a teaching analogy. Inspecting a part highlights its role; it does not execute or simulate the software. Cabinet trays are records, workpieces are data, and latches are checks. Unless an explanation states a quantity, compartments and sample workpieces do not denote data counts. Part dimensions are not a quantitative scale.
3 · Security headers
HTTP headers that constrain what the browser will do, limiting damage if something else fails.
| Header | Purpose |
|---|---|
| Content-Security-Policy | whitelist which scripts can run (see xss and csrf) |
| X-Frame-Options | stop your site from being embedded in an iframe (clickjacking) |
| Strict-Transport-Security | force HTTPS |
| X-Content-Type-Options | stop MIME sniffing |
Most frameworks ship this as a one-line middleware: Helmet (Express), or the equivalent in Django/Echo/Gin. Enable it rather than hand-rolling each header.
The mindset that ties it all together
Every vulnerability in these notes is about boundaries: data crossing between systems, privilege levels, languages, or markup:
- SQL injection: untrusted input crossed into the database query boundary.
- XSS: user markdown crossed into the HTML boundary.
- Broken authorization: a request crossed the boundary of what different users may access.
No single defense is perfect: think in layers: validate input → parameterize operations → authorize at the point of access → security headers → monitor and log. An attacker has to break all of them at once, which almost never happens.
Terms: GLOSSARY · Up: security mindset