Your first security audit, if you ship a small web product
The first audit on a small product is rarely a hunt for the clever bug. It's a fight against the boring ones — and an argument with the founder about which week-one finding they actually have time to fix.
I want to write down what that first audit actually looks like, because the public-facing version (the checklist post, the SOC 2 listicle, the OWASP top-10 page that's been re-skinned for the eighteenth time) doesn't match what we do on Monday morning when a small SaaS hands us a staging URL and a test account.
If you run a ten-person product and you've been told you "need a pentest," this is the post I wish someone had handed me before my first one.
The first two days are about your data, not your code
Most first-time audits open with the auditor running a scanner and the founder watching the dashboard nervously. That's the wrong opening move. The scanner finds the same things on every site (missing headers, an outdated jQuery, a verbose error page) and you've already paid for that information twice over.
What we actually do on day one is sit with whoever wrote the schema and ask: which row in which table would ruin your week if a stranger read it?
The answer is almost never "users." It's usually a join table that nobody thinks about. Invitations. Webhook secrets. Embedded form submissions. A "magic link" table that contains live tokens for accounts that haven't claimed them yet. Once we know what the crown jewels are, every later finding gets ranked against them — and 80% of the noise drops out.
A small SaaS we audited last year had ten tables. Nine were obvious. The tenth was impersonation_grants, used once a quarter by their support team. Every interesting finding in the report ended up touching that one table.
The four surfaces we actually look at
For a small product — say, < 20 backend routes, one or two integrations, no internal admin console worth the name — there are four surfaces that consistently produce findings worth paying for. Everything else is a distraction in the first audit.
1. The "who am I" boundary
Every request your API answers must, somewhere, resolve to: which account is this user looking at? The boundary itself is rarely missing. What's missing is the second check: and are they allowed to look at it?
This is where IDOR-in-the-billing-endpoint lives. It's also where 60% of bountable bugs on small SaaS come from. We spend roughly a third of the first audit here, and we never regret it.
2. Anywhere your server fetches a URL on behalf of a user
Webhook destinations. OAuth callbacks. Avatar import. "Fetch a screenshot of this URL." OpenGraph previews. Any time the user types a URL and your server reaches out to it, you have a trust boundary that is older than most of your code. We have a separate post on the patterns we keep seeing.
3. The file-and-blob layer
Uploads and downloads sound boring until you realize how often a presigned URL outlives the permission it was granted under. The "fence" you think a signed URL gives you is usually a five-foot ribbon. We always check this — even (especially) when the team tells us they "use S3, so it's fine."
4. The forgotten admin and beta routes
Every small product has at least one. A /admin/_internal/csv behind a header check. A feature-flagged beta page that uses a stale auth helper. A "v1" endpoint that the new frontend stopped calling six months ago. We always find these on day three or four — and they always have a different mental model of auth than the production code.
What we deliberately skip on the first audit
This part annoys people, so I'll say it plainly: on a first audit for a small product, we don't run a long DAST scan, we don't audit your dependency tree by hand, and we don't write up missing security headers as a finding worth a section.
Not because those don't matter. They do. We skip them because:
- Your tool of choice already tells you which deps are vulnerable. You don't need us to re-tell you.
- A DAST scan on a small app surfaces < 5% real findings, and the false positives chew through the engineering attention you have for the report.
- Headers are a one-paragraph appendix, not a chapter.
The first audit's job is to find the one or two bugs that have actual blast radius. Save the housekeeping for a second pass.
How we actually run the week
For a small product, here's the rhythm we follow. It's not gospel; it's just what's worked across maybe a hundred small-product engagements at this point.
Day 1 ── interviews + threat-model the data layer
Day 2 ── auth boundary deep-dive (one user, two users, three orgs)
Day 3 ── server-side fetch + integration surfaces
Day 4 ── file/blob surface + presigned URL lifetime audit
Day 5 ── beta/admin/forgotten routes + write-up
Day 6 ── re-test top findings on a clean account
Day 7 ── report draft + 30-min call with the team
Notice what isn't there: a "scanning" day. Scanning happens in the background from day one. It is not the work.
The report your engineers will actually read
This is the part where most audit shops lose the room. They deliver a 60-page PDF with severity bars, and the engineering team reads the executive summary and the first three findings before going back to shipping. We do it differently, and I'll defend the format until I die:
- One page per finding. One.
- Reproducible HTTP transcript at the top, before any prose.
- "The exact line we'd change" in your code, by file and line number. Not "consider implementing."
- A "why this is real" section that explains the impact in your product's vocabulary, not in CVSS abstractions.
- A list of related places in your code that probably have the same issue, even if we didn't verify them — for example, every other route that mirrors the billing-endpoint shape. Treat it as the auditor's TODO, not yours.
If you only get one thing from this post, get this: the report is the deliverable, not the audit. A finding that doesn't ship as a one-page artifact your engineers can hand each other in a Slack DM is a finding that won't get fixed.
What a "good" first audit costs you
Money-wise: in the small-product world we live in, we've seen serious independent audits range from about $4k to $12k for a one-week engagement. Anything cheaper is a scanner with a logo. Anything more expensive is selling you a brand, not a finding.
Time-wise, on your side: about six hours of engineering attention, spread over the week. One hour on Monday for the kickoff, two hours mid-week for clarifying questions, an hour Thursday for the upload-flow walkthrough, and a 30-minute readout call at the end. That's it. If your auditor is asking for more, ask them why.
Three things you should do before the audit starts
You don't need to "prepare for the audit." But three small moves make the week dramatically more useful:
- Give us a real test account. Not a god-mode account. A normal one. Two of them, ideally, in different orgs.
- Write down your "what would ruin our week" list. Three rows from three tables. Don't overthink it.
- Tell us about the route you're embarrassed by. Every product has one. We'd rather hear about it than discover it.
That's it. No spreadsheet, no SOC 2 evidence pack, no "asset inventory." If an auditor demands those before a small-product engagement, they're optimizing for their own process, not yours.
If you only read one section
The first security audit for a small product is not a checklist. It's not a scan. It's a week of someone sitting with your data model, finding the one or two routes where the question "is this user allowed to do that?" is answered with "probably," and turning that into one page per problem.
Everything else is theater.
Read next
Want the first heads-up free?
We'll do a non-intrusive look at your product and tell you the top three things to fix. If you don't need a paid audit, we'll tell you that too.
Request a free check