Security at a glance
Every system we put on the internet is probed by automated scanners within days. This page shows the layers of defence every project needs and the baseline we expect on day one. Read it before anything goes live.
How it works
Each layer assumes the one before it can fail. The WAF will miss things, so the app checks access. The app will have bugs, so its database role can do very little. Something will eventually get through, so detection must notice it quickly.
The baseline
| Layer | Must have from day one | Page |
|---|---|---|
| API | Ownership check on every object, rate limits and lockout on sign-in, input validation, no internal routes or API docs on public hosts, secrets never logged | API security |
| Web | Security headers and CSP, safe cookies, trusted proxy headers only, admin panels not reachable from the open internet | Web security |
| Mobile app | The app is treated as untrusted, attestation on sensitive calls, no secrets in the binary, no fixed review codes in production | Mobile app security |
| Infrastructure | SSO with MFA for every person, audit trail and threat detection on, WAF blocking, no public database tools, least-privilege database roles | Infrastructure security |
| People and process | No default passwords, secrets rotated after any exposure, regular log reviews, an incident lead | Attacks we faced |
Rules
No default or shared passwords anywhere, ever. Every admin account is created with a unique generated password and MFA. A seed script must never create an admin with a known password.
Anything that is not for the public is not reachable by the public: admin panels, database tools, internal APIs, API documentation, monitoring. Put them behind SSO, a VPN, or mutual TLS.
When a secret may have been exposed, rotate it the same day, then find out how it leaked. Rotating without fixing the cause only buys hours.
Security controls are tested, not assumed. A WAF in count mode, a log filter that misses a header, or a gate that is disabled in production all looked fine on paper.
What our incidents taught us
Details are in Attacks we faced. In short:
- The systems that were breached had a default admin password, internal endpoints open to the internet, a public database admin tool, or an application database user with far more rights than it needed.
- The systems that held had access checks on every call, rate limits and lockout, internal routes guarded by a key, and an edge that refused unknown hosts.
- Our near misses were secrets in logs, a token in a git remote URL, a fixed review code in production, and a WAF that blocked nothing because it was left in count mode.
Checklist
- The baseline row for every layer is in place before launch.
- No default passwords; every admin has MFA.
- Nothing private is reachable from the internet.
- Detection is on and someone reviews it weekly.
- The project's security checklist is filled in. See Security checklist.