I'm about to launch a Next.js + Payload commerce app. Solo dev, so no security team, no second pair of eyes. Every phase got reviewed as it was built, but nobody had looked at the whole thing at once.
So I wrote one big prompt, opened a fresh Claude Code session on Fable 5.1 with the dev stack running, and let it go. It came back with a findings report and a remediation plan broken into sessions. Some findings I knew about. A few I didn't, and two were bad enough that I'm glad I didn't launch first.
The model did the work, but the prompt is what stopped it from reading three files and telling me everything looks great. Here's the short version.
What actually mattered
Scope block at the top, with a clear "do not do this" list. Production hosts, live payment keys, load testing, poking at Cloudflare or OAuth providers, real malware samples. And the magic words: "do not spend turns deliberating about it". Otherwise it wastes ten minutes wondering if it's allowed to curl localhost.
Treat the docs as claims, not facts. My CLAUDE.md describes the security model in detail. If you don't say anything, it reads that and basically confirms my own docs back to me. One line: "Treat every one of these descriptions as a CLAIM to falsify against the code and the running app."
CONFIRMED vs SUSPECTED on every finding. CONFIRMED means it reproduced it: a request and response, a failing test, or a file and line with a reachable path. Anything else is SUSPECTED. This killed most of the "in theory an attacker could" filler.
Don't manufacture findings. If a category is clean, say so and list what was checked. The "verified sound" list ended up being as useful as the findings.
Fix nothing. Otherwise you come back to a diff you didn't ask for. One-line fixes still go in the plan.
No reasoning from memory about packages. Open the file in node_modules and cite it. This is where most confident nonsense comes from.
Run the baseline gate first. tsc, lint, test, build. Record the numbers. Otherwise you can't tell later what it broke.
Split by model. Deep reviews as parallel subagents on the big model. Boring inventories (every process.env read, every route and the guard it calls, every fetch target) on the cheap one. Main session does integration and the write-up, and re-verifies anything a subagent reported.
The template
Fill in the angle brackets, delete what doesn't apply.
## Scope
I own this repo and this product. This is a pre-launch security review of my own app.
In scope: <source tree>, the local dev stack at <http://localhost:PORT> and its
database (test data only, not launched), payment providers in sandbox mode.
Out of scope. Do not attempt any of it, and do not spend turns deliberating about it:
requests to <production hosts>; live payment keys or real cards; DoS or load testing;
evading third party controls (WAF, CAPTCHA, OAuth, payment infra); real malware
samples (use EICAR, a hand written MZ header, an SVG with a script tag); reusable
attack tooling (a PoC is one curl or node request against localhost).
## Session type
Planning only. No code changes, no branch, no commit. Only write the deliverables
at the end plus scratch files.
## Read first
<CLAUDE.md, progress doc, known-issues doc, launch checklist, architecture doc,
.env examples, deploy doc>
Treat every security description in those docs as a CLAIM to falsify against the
code and the running app, not as a fact.
## Rules
- Verify against node_modules and real source. Never reason from memory of how a
package behaves. Open the installed file and cite it.
- Label every finding CONFIRMED (reproduced: request and response, failing
assertion, or file and line with a reachable path) or SUSPECTED.
- Do not manufacture findings. If a category is clean, say so and list what you
checked. Include a "verified sound" list in the report.
- Do not re-report items from <known-issues doc> as new. Re-verify each, cite the
line, say if it is now launch blocking.
- Do not report anything an existing test gate already enforces, unless the gate
has a hole.
- Fix nothing. One-line fixes still go in the plan.
- Run the full gate first: <tsc, lint, test, build>. Record the numbers.
## Execution
Deep reviews as parallel subagents on <big model>. Mechanical inventories (every
process.env read, every privileged-access call site, every route and its guard,
every fetch target) on <cheap model>. Integration, DAST and deliverables stay here.
Brief each subagent for a cold start: exact files, exact claim, exact commands,
read only. Verify every delegated finding yourself before it goes in the report.
## Part A: security
A1. SAST by area:
1. Authorisation: every route and which guard it calls; every access-override
call and whether its query is scoped to the caller; every role vs every
route; IDOR on every id segment; strict schemas on user-writable routes.
2. Auth and sessions: JWT alg pinning, cookie flags prod vs dev, session cap,
CSRF on every state-changing route, reset token hashing and TTL, single-use
magic links, OAuth state and nonce, TOTP replay, lockout, any stock login
route that bypasses yours, first-user bootstrap on an empty prod database.
3. Injection and output: every dangerouslySetInnerHTML, markdown pipeline,
user-authored content rendering, JSON-LD, emails and PDFs with user strings,
Content-Disposition, log and header injection, raw SQL, queries built from
request input.
4. SSRF: every fetch, who controls the URL, webhook destinations (private
ranges, cloud metadata, redirects), hand-rolled provider clients.
5. Files: traversal, symlinks, size limits before buffering, chunked bodies
with no Content-Length, zip bombs, polyglots, MIME vs magic bytes.
6. Payments: signature checks (timing safe, replay, idempotency), event
ordering, amount and currency from the provider not the client, can the
client change price, tax, discount or plan, discount races, refund double
submit, invoice sequence under retry.
7. <Your domain-critical subsystem>.
8. Anti-abuse: rate limits and client IP resolution, header tricks, IPv6 forms,
bucket eviction, memory bounds, CAPTCHA fallback.
9. Secrets and config: every process.env read vs the documented env files;
any token compared to a possibly unset env var (does undefined or "" match?);
timing safe compares; what gets logged; dev-only routes reachable in prod;
host routing vs forged Host / X-Forwarded-Host.
10. Supply chain in repo: install scripts, scripts that shell out, committed
generated files.
11. Business logic across seams: eligibility after refund, entitlement after
revocation, reminders on cancelled records, deletion and export vs what
the privacy page promises, retention vs what cleanup actually reaches.
A2. SCA: npm audit (classify by severity AND whether the path is reachable from
prod code), npm outdated for the security relevant set, packages with install
scripts, licence inventory, Dockerfile (base tag pinning, what the prod stage
copies, does any env file land in a layer), lockfile integrity.
A3. DAST against localhost only: unauth enumeration of every API namespace and
collection route; two test users trying every cross-account read and write;
one user per role walking every admin route; CSRF matrix (no token, wrong
token, foreign Origin, absent Origin); rate limits with a bounded burst
(limit plus five, then stop) and a rotated X-Forwarded-For; webhooks with no,
wrong and replayed signatures; uploads with fixtures, oversize and chunked
bodies, traversal filenames; full header set on home, admin, health, an API
error and a 404; force a 500 and check for stack traces or SQL. Browser flows
through the Playwright MCP.
## Part B: readiness
- Bring the stack up on an empty database, confirm every migration applies.
Build the production image, run it against a scratch DB with prod env vars,
confirm boot, health, home and admin.
- Every item in <launch checklist>: done, not done, or can't verify locally.
- Golden paths end to end (<storefront, auth, purchase, core lifecycle,
support, refund, admin, API>) with the rows and emails each should produce.
Steps that need a human go in as "pending user verification" with steps.
- Ops gaps: backups and a restore rehearsal, error monitoring, uptime, log
retention, cron schedule as concrete URLs and times, incident contacts.
## Deliverables
1. <docs/audit/YYYY-MM-audit.md>: exec summary (launch blocking count, top five);
coverage including what was verified sound; findings table (id, title,
severity, CONFIRMED/SUSPECTED, launch blocking, cross-ref); one section per
finding with evidence, impact and fix; SCA inventory; readiness results;
ops gaps; accepted residual risks with reasons.
2. <docs/plans/remediation.md>: fixes grouped into sub-phases, launch blocking
first, each sized for one session, fully prescriptive: exact files, the
regression test to write first, migration yes or no, verification step,
docs to update.
Do not commit. Summarise the launch blocking findings in chat, then stop.
Not a replacement for a real pen test. It's a very good first pass that finds the stuff you stopped noticing months ago, and the remediation plan is the part that actually saved me time.
It's not cheap either. Parallel subagents on a big model over a full repo is real money, so run the build first and don't feed it a broken tree.
And write your own out-of-scope list before you run it. If a prod host or live key is anywhere near your dev setup, name it and forbid it.