Work / Audit
A security review of an AI-built SaaS platform
A four-phase security review of a multi-tenant SaaS written mostly by an AI coding assistant: every candidate issue challenged, every finding checked by hand and worded for the owner.
What they needed
A business-to-business platform: agencies run programs for their client organizations, with public pages, forms, quizzes and challenges for participants, and admin areas for each organization and agency. Many organizations share one installation, so each one must only ever reach its own data.
Most of the code was written by an AI coding assistant: three out of four commits up to the review carried its co-author mark. There were no automated tests. I was asked to review the code for security: who can see, change or delete what, with and without logging in.
How it ran
The review was static and read-only. One frozen version of the code was reviewed from start to finish. Nothing ran against the live platform, and I made no fixes along the way.
- Baseline, 19 August 2026. The version under review was frozen and inventoried, and a first checkpoint went to the client the same day.
- Phase 1, delivered 25 August. The main review: 547 candidate issues, 65 findings. Three High findings went to the client a day ahead of the package.
- Phases 2 and 3, delivered 7 and 24 September. Further passes, adding ten findings and 33 open questions the code alone could not answer.
- Final package, 29 September. Everything in one place, with a walkthrough.
Every candidate went through the same steps:
- Tooling, not a model, mapped the code. It listed what the platform exposes: 27 route handlers and 237 server actions, 141 of them in a single file.
- One AI model analyzed each piece in a fresh session, with a fixed answer format, so no answer leaned on the one before.
- A separate session tried to disprove every candidate. 317 could not be proven from the code alone. They were not reported as findings.
- Duplicates were merged by the security rule they broke, and severity was scored with CVSS 4.0, calculated by a library rather than estimated.
- I read every finding, and checked each High one against the source a second time. Nothing went to the client until I had approved that exact package.
What they got
For every phase: a summary, an index of findings, one document per finding, and a list of what the review could not establish. Each finding gives its severity and CVSS score, the affected files and lines, how an attacker gets there, what it costs the business, and what to do about it.
The final package held every finding, the limitations, and a walkthrough: summary, scope and method, an overview of the attack surface, and an order for the fixes, grouped into workstreams. Questions were handled by email.
Retesting was not part of the job. By the client’s own account, several High findings were fixed within days of the first package.
What it showed
Most findings were about access. In Phase 1, 43 of 65 were one user reaching data or actions that belonged to someone else: a customer account the platform treated as one of its own staff, challenge results anyone could forge, links that kept working after they should have stopped.
The code showed its origin in other ways too. The documentation disagreed with the code: a page it described did not exist, and storage it called private was public, and the other way round. Some restrictions lived only in the interface, so calling the server directly skipped them. And with no tests, nothing would have caught a regression.
None of these show up in normal use. They show up when someone reads the code asking what it lets people do.
Security review / AI-built SaaS platformclient anonymized
- 0Critical
- 14High
- 49Medium
- 12Low
Method: deterministic tooling built inventories of the code, one AI model analyzed each candidate finding and a separate one tried to disprove it, and I checked every finding by hand before it went into the report.
| ID | Severity | Finding | Status |
|---|---|---|---|
| F-037 | High | Anyone with the public challenge link could log activity under another participant's name and push them up the leaderboard. | Fixed by client |
| F-007 | High | A customer account labeled "superadmin" was treated as one of your own staff, with power over every other customer's data. | Fixed by client |
| F-058 | Medium | Two AI features worked without logging in, so a stranger could run up your AI bill. | Reported |
3 of 75 findings, worded for the business owner. Status as reported by the client after delivery.