Five checks before you ship
Five checks we run before any release goes out. Each one explains what it means, what skipping it costs you, and gives you a sandbox that puts the failure next to the fix.
Your ticks stay in this browser. Nothing is sent to us.
Where this release currently stands
Tick a check once you have verified it in your own environment. The sandboxes below explain each one, but they never tick anything for you.
Release status
0 of 5 verified — not readyStatus of each check
Users can only reach records they own
What it means
Authentication proves who you are. Authorization decides what you may open.
Every protected endpoint has to confirm the caller actually owns the record being requested, normally by matching the record's owner ID against the signed-in user's ID.
Why it matters before you ship
The failure has a name: an insecure direct object reference, usually shortened to IDOR. It is the most common serious bug we find in web applications.
If
/api/orders/123
hands back the order without checking who asked, anyone can walk the ID range and read other customers' data.
Random UUIDs make guessing harder, but a UUID is not an authorization check. You still need an explicit ownership test on every request.
Try it: one request, with the check and without
SandboxReset links expire, and work exactly once
What it means
A reset link carries a single-use token. That token needs a short lifetime — fifteen to sixty minutes is normal — and must stop working the moment it is used or a newer one is issued.
Why it matters before you ship
Reset links land in mailboxes. Mailboxes get forwarded, screenshotted, left open on shared machines and turn up in breach dumps.
A token with no expiry is a permanent back door into the account. A short lifetime shrinks that window from forever down to minutes.
Try it: the life of a single reset token
Sandbox-
1
Issue the reset link
Creates a single-use token with a fifteen-minute lifetime.
-
2
Let time pass
Moves the clock twenty minutes on, past the token's lifetime.
-
3
Redeem the token
A live token sets the password once. An expired or spent token is refused.
-
4
Request another reset
Issuing a new token has to kill the previous one immediately.
Treat every value from the client as hostile
What it means
Assume everything the client sends is hostile. Validate types, lengths and formats before anything else runs.
Use parameterised queries or an ORM so input can never change the shape of a SQL statement, and escape anything rendered back into a page so an injected
<script>
tag cannot run in somebody else's browser.
Why it matters before you ship
SQL injection can read or drop an entire database. Cross-site scripting can steal a session and become account takeover.
Both have sat in the OWASP Top 10 for over a decade because they keep working, usually on the one field somebody forgot.
Try it: the same payload, raw and handled
SandboxThe API answers your own domains only
What it means
CORS, or cross-origin resource sharing, tells browsers which sites may call your API. In production that list holds your own domains — not a wildcard, not localhost, not whatever was convenient while developing.
Why it matters before you ship
A wide-open policy lets a malicious site make authenticated calls to your API from a victim's browser, leaking data or acting on that person's behalf.
Teams ship
Access-Control-Allow-Origin: *
out of a development config more often than anyone would like, and usually notice only once something abuses it.
CORS is a browser protection. It does nothing about server-to-server requests. Authentication and authorization still do the real work.
Try it: which origins get through
SandboxExpensive endpoints need a ceiling
What it means
Cap how many requests one client — identified by IP address, account or API key — can make inside a time window.
Put tighter limits on the expensive and abusable routes: sign-in, password reset, sign-up, search, and anything that sends email or SMS.
Why it matters before you ship
Without a ceiling, four things are on the table:
- Brute force against sign-in and password-reset endpoints.
- Credential stuffing run at the scale of a leaked password list.
- Denial of service from one noisy client, deliberate or not.
- A surprise cloud bill when something loops your costliest route overnight.
Try it: burst past the limit
SandboxExport the result
Copy your status as Markdown for a pull request, or as JSON for a pipeline step. The report is generated in English so it reads the same in any repository.
Ticks live in this browser under a single local storage entry. Clearing site data clears the checklist.
Want us to run this against your stack?
We work through these five checks, plus the rest of our review, on every system we build and on systems we inherit. A briefing takes half an hour.