// FIELD NOTES 2026.04.10 3 min read appsecpen-testchecklist

Eighteen months in, we’ve completed 38 engagements. They span fintechs, fleet- management SaaS, two robotics companies, and a healthtech firm we can’t name. Different stacks, different teams, very different threat models.

And yet — the same six findings appear in roughly the same order, every time.

Treat this list as a pre-emptive remediation roadmap. If you can knock these out before our next visit (or, ideally, before someone else’s first visit), the rest of the engagement is materially more useful.

The list

#FindingSeverityTime to fixNotes
01Long-lived API keys in CICRITICAL4hRotate to OIDC
02Public S3 / blob containersCRITICAL2hAudit, lock down
03Stale admin accountsMEDIUM6hDisable inactive 90d+
04Missing 2FA on SaaS adminMEDIUM3hEnforce in IdP
05Forgotten staging subdomainsMEDIUM1dDNS sweep + decommission
06Verbose error pages in prodLOW2hStack traces leak path info

Roughly three engineering days of work, total. The probability that one of them is currently true for you, right now, is empirically around 91%.

Why these six, in this order

01 · Long-lived API keys in CI

This is finding #1 because it’s the cheapest to find and the highest-impact when it works. A GitHub Actions log with AWS_SECRET_ACCESS_KEY printed during a terraform plan is a full account takeover.

Fix: migrate to OIDC federation. GitHub, GitLab, and CircleCI all support short-lived tokens issued at workflow start.

02 · Public storage buckets

We run a small script that enumerates bucket names from your domain prefix and tests each for anonymous read. We have never run an engagement where this returned zero results.

The fix is one-line — apply a Block public access policy at the account level — but it requires an inventory pass to confirm no legitimate consumer is broken by it.

03 · Stale admin accounts

Every company we’ve tested has between three and twenty admin accounts for former employees, former contractors, or former vendors. Most are protected only by a password the user reused on three other services.

The fix is a 90-day inactivity sweep across every system that authenticates people, plus enforced 2FA on every account that survives.

04 · Missing 2FA on SaaS admin

Related to #03 but worth its own bullet because the surface is broader: it’s not just your admin console. It’s GitHub, GitLab, AWS, GCP, Datadog, Sentry, Stripe, Notion, and twenty others.

If your IdP supports it, enforce 2FA on the admin role globally. Don’t ask, don’t notify, don’t email a “deadline.” The exemption list goes to one.

05 · Forgotten staging subdomains

This is the subtle one. staging-old.example.com was decommissioned, but the DNS record still points at a Heroku app from 2022 that’s now available for anyone to claim.

The script in our recon-tools repo will enumerate yours from certificate-transparency logs — run it on yourself before someone else does.

06 · Verbose error pages in production

The lowest-severity item on the list but worth the two hours. Stack traces on 500 responses leak file paths, dependency versions, and (in Django’s default error page) sometimes environment variables.

Turn DEBUG = False on. The error page should say “something went wrong.”

What this list isn’t

It is not defense-in-depth. It is not a substitute for a real threat model. It will not stop a determined adversary.

It will, statistically, catch the opportunistic 80% — which is who is going to ruin your week.

One more thing

If you’ve fixed all six and want a real engagement, we should talk.


Found this useful? Send it to someone who'd benefit, or email us a question.