Use when a codebase needs an adversarial security review or compliance readiness assessment — web UI and API security, authentication and access control, licensing or paywall bypass, secrets exposure, dependency vulnerabilities, and SOC 2 / ISO 27001 / HIPAA / PCI DSS / GDPR readiness; when the user mentions security audit, pen test, red team, blue team, purple team, white team, tabletop or adversary emulation, SOC 2, compliance, Vanta, hardening, or says \"/auto-audit-security\"; or when abo...
Scanned 9/3/2026
Install to Claude Code
npx -y skills add mr-tbot/BOT-CODE-MODS --skill auto-audit-security --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Auto Audit Security?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/mr-tbot-auto-audit-security)More formats (shields.io, HTML) on the badges page.
---
name: auto-audit-security
description: "Use when a codebase needs an adversarial security review or compliance readiness assessment — web UI and API security, authentication and access control, licensing or paywall bypass, secrets exposure, dependency vulnerabilities, and SOC 2 / ISO 27001 / HIPAA / PCI DSS / GDPR readiness; when the user mentions security audit, pen test, red team, blue team, purple team, white team, tabletop or adversary emulation, SOC 2, compliance, Vanta, hardening, or says \"/auto-audit-security\"; or when about to call a system secure or compliant."
---
# /auto-audit-security
An adversarial security review of this codebase, plus an honest compliance-readiness assessment —
findings first, fixes only when you approve them.
**The boundary, stated once and never blurred: a code audit produces INPUT EVIDENCE to a compliance
program. It never produces the compliance artifact.** SOC 2 is an attestation engagement performed
under SSAE 18 by an independent licensed CPA firm; ISO 27001 is certified by an accredited body. What
this skill produces is a **readiness assessment**: which technical controls are evidenced in the code,
which are missing, and what an auditor will ask for that no repository can answer.
Two facts worth getting right, because vendors routinely get them wrong:
- The Trust Services Criteria comprise **61 criteria**, of which **18 are the privacy category**.
Higher counts in circulation (64, 80+) come from counting *points of focus* as criteria — they are
explicitly not criteria.
- **A SOC 2 report is restricted-use. SOC 3 is the general-use report.** If the goal is something
publishable on a marketing site, that is SOC 3, and confusing the two misdirects the whole effort.
Everything this skill generates is **IPE — information produced by the entity.** A service auditor
will test its completeness and accuracy before relying on it, so every artifact must record how it was
produced, over what population, and at what time.
## Step 1 — Scope And Authorization
Establish before running anything:
1. **What is in scope** — repo only, or deployed environments too? Which environments?
2. **Authorization for active testing, in writing.** Static review of code you own needs none. **Any
active scan (ZAP, nuclei, fuzzing, credential testing) requires explicit written authorization
naming the specific target, and must never be pointed at production, at shared infrastructure, or
at a third party.** Staging, a local instance, or not at all. Third-party-hosted components have
their own testing policies and are frequently out of bounds regardless of who owns the account.
3. **Which frameworks matter** — SOC 2, ISO 27001, HIPAA, PCI DSS, GDPR/CCPA, or none. Ask; do not
assume, since the applicable set drives everything downstream.
4. **Where findings may be written.** Not a public issue tracker. See Handling below.
## Step 1b — Decide Which Seats You Are Sitting In
An audit run from one seat produces one class of finding, and the classes it cannot produce look
exactly like an absence of problems. Name the passes before you start, and record which you are
**not** running and why — that list belongs in the report's methodology section, because an
unexercised seat is a coverage gap, not a clean result.
The colours are the InfoSec colour wheel (April C. Wright, 2017): red, blue and yellow are primary;
purple, orange and green are their combinations. **White is the referee** — NIST defines a White Team
as the group refereeing an engagement between a Red Team of mock attackers and a Blue Team of
defenders, and here it is the seat that owns authorization, scope and evidence. **Black is not a
standard term**; it is used here for the surface that is not the application.
| Pass | Seat | What it establishes | Needs authorization? |
|---|---|---|---|
| **Red** | attacker | Reach an objective the way an attacker would: chain the medium findings, abuse the intended feature, bypass the paywall, escalate the role. Objective-led, not checklist-led | **Yes** for anything active |
| **Blue** | defender | Would anyone have noticed? Are the auth failures, privilege changes, exports and admin actions logged, retained, alertable and attributable? Can you answer "what did this account do" | No |
| **Yellow** | builder | Is the security control implemented where every caller passes through it, or reimplemented per route? Are the primitives the platform's own, or hand-rolled | No |
| **Purple** | red + blue | For every Red finding: a **detection** for it, and a regression test. This is the pass that converts a one-off exercise into standing coverage | No |
| **Orange** | yellow + red | For every Red finding: the change to *how it is built* that removes the class — a middleware, a type, a default, a lint rule | No |
| **Green** | yellow + blue | Deployment reality: TLS and headers as actually served, secrets as actually injected, permissions on the running artifact, the database reachable from where it should not be | Read-only unless authorized |
| **White** | referee | Authorization in writing, rules of engagement, what is out of bounds, what counts as evidence, where findings may be written, and the severity adjudication when passes disagree | Owns it |
| **Black** | outside the app | Physical access, devices and removable media, the supply chain (dependencies, build infrastructure, signing keys, CI credentials), and the human path — support tooling, account recovery, social engineering. Almost always the least-tested surface | **Yes**, and usually out of scope |
**Authorization is per pass, not per audit.** White grants Red and the active half of Green. Blue,
Yellow, Purple and Orange are review passes over code and configuration you already own and need no
new permission. Never let a Red objective drift into a Black one — social engineering and physical
entry require separate, explicit, written authorization naming the people and premises involved, and
their absence is a hard stop, not a judgement call.
**Purple and Orange are derived.** They consume Red's findings, so they produce nothing before Red has
run, and a report claiming them without a Red pass behind them is describing work that did not happen.
**The most common real outcome** on a first audit is that Blue finds nothing to look at — no
authentication logging, no alerting, no retention. Record that as the finding it is. "We would not
know" is a more serious result than most of the mediums the scanners produce.
## Step 2 — Map The Attack Surface
You cannot audit what you have not enumerated. Produce the inventory first:
- **Every route/endpoint**, with method, and whether it is authenticated
- **Every trust boundary** — where untrusted input enters, where privilege changes
- **Every authentication path**, including recovery, SSO, API keys, and service-to-service
- **Every entitlement check** — what gates a paid feature, and where that check executes
- **All data stores**, and what class of data each holds (PII, credentials, payment, health)
- **All third-party integrations** and what each is trusted with
- **The shipped client bundle** and any mobile binary, treated as fully readable by an attacker
This inventory is the denominator for everything after it. A review that samples routes will miss the
one unprotected endpoint, and that is the one that matters.
## Step 3 — Access Control, Route By Route
**This is the class scanners systematically miss, and the class most likely to be exploitable.** It
cannot be sampled and it cannot be delegated to a tool.
For **every** route in the inventory, answer explicitly:
- Does it authenticate? Does it *authorize*, separately?
- Is the authorization check **server-side**? A check in the UI layer is not a check.
- Does it verify the caller owns the object it operates on, or only that the caller is logged in?
(That gap is IDOR/BOLA, and it is the most common serious finding in real applications.)
- Can a parameter change the identity or scope of the operation (mass assignment, tampered
`user_id`, tampered price or quantity)?
- Are administrative functions protected by a role check on the server, or only unlinked in the UI?
Produce a table with a row per route and an explicit verdict per column. "Probably fine" is not a
verdict — trace the code path to the check, or record it as unverified.
## Step 4 — Licensing And Paywall Bypass
Treat the client as fully hostile and fully readable — it is.
- **Entitlement evaluated client-side.** If the client decides whether the user is premium, the user
decides whether the user is premium. The server must gate the data, not just the UI.
- **Feature flags that only hide UI.** Hidden is not disabled. Call the endpoint directly and see what
comes back.
- **Trial or license state stored on the device** — local storage, preferences, a file, a registry key.
All user-writable.
- **In-app purchase receipts validated on device.** Receipt validation belongs server-side, against the
store's API.
- **Secrets in the shipped bundle**: API keys, signing keys, admin endpoints, or private hostnames in
JS bundles, source maps, or a mobile binary. Extract and grep the actual artifact rather than the
source tree.
- **Premium data on unauthenticated endpoints** — the paywalled screen calls an API; call it directly
without a session.
- **Quota and rate limits enforced only in the client.**
- **Price, quantity or plan sent from the client** and trusted by the server.
For each: the correct design is that the **server independently determines entitlement on every
request** from state the user cannot write.
## Step 5 — The Rest Of The Classes
Cover the current OWASP Top 10 and API Security Top 10. **Always name the edition — write `A01:2025`,
never a bare `A01` or "OWASP Top 10"** — and confirm which edition any scanner ruleset actually
encodes before citing it as coverage. Supply-chain findings map to **A03:2025 Software Supply Chain
Failures**. Pull the current codes at audit time rather than reciting them.
By class, with the concrete question to answer in this codebase:
- **Injection** — SQL/NoSQL/command/template/LDAP. Is every query parameterized? Is any shell command
built from input?
- **Authentication** — session fixation, rotation on privilege change, lifetime, logout invalidation.
JWTs: is the signature actually verified, is `alg` pinned, are `exp`/`aud`/`iss` checked, is the
secret strong? OAuth/OIDC: strict `redirect_uri` matching, `state`, PKCE.
- **Password storage** — a current memory-hard KDF with current parameters. Verify against present-day
guidance rather than a number remembered from years ago.
- **Cryptographic failures** — legacy algorithms, ECB mode, static or reused IVs, homegrown crypto, keys
in source, missing TLS verification, certificate pinning that was disabled "temporarily".
- **SSRF** — any server-side fetch of a user-supplied URL, including webhooks, previews and importers.
- **XSS and CSP** — output encoding by context, `dangerouslySetInnerHTML` and equivalents, and whether
CSP is real or `unsafe-inline`.
- **CSRF and SameSite**, on every state-changing endpoint that accepts cookies.
- **Deserialization, XXE, file upload** — type and size validation, storage location, execution
prevention.
- **Logging** — are credentials, tokens or PII being logged? Is there enough logging to reconstruct an
incident? Both failures are findings.
- **Error handling** — stack traces or internal paths returned to clients.
## Step 6 — Run The Scanners, Then Distrust Them
Automation is the floor, not the audit. It is good at known-vulnerable dependencies and hardcoded
secrets, and poor at logic and access control. **State that in the report**: the access-control
findings in Step 3 have no tool path at all, so a reader must not read a clean scan section as
covering them.
**Separate the reporting run from the gating run.** They need different flags, and combining them is
how a gate silently narrows: a filter that reduces noise in a report also reduces what the gate can
fail on.
```bash
# SAST — --error is required for gating; semgrep exits 0 with findings without it
semgrep --config=<pinned-local-rules> --sarif -o semgrep.sarif --metrics=off . # report
semgrep --config=<pinned-local-rules> --error --metrics=off . # gate
pipx install 'bandit[toml,sarif]' && bandit -r src/ -f sarif -o bandit.sarif # exits 1 on findings
gosec -fmt=json -out=gosec.json ./...
# dependencies — prefer reachability where available
osv-scanner scan source -r . # 0 = clean, 1 = findings, 128 = TOOL FAILURE, never a pass
govulncheck ./... # Go, reachability-aware
pip-audit -r requirements.txt ; cargo audit ; npm audit --omit=dev
grype <target> --only-fixed -o table # report: actionable subset
grype <target> --fail-on high -o json --file out.json # gate: no fix-state filter
trivy fs --scanners vuln,secret,misconfig,license --severity HIGH,CRITICAL --exit-code 1 \
--format sarif -o trivy.sarif . # 0 clean, 1 findings, other = tool error
# secrets — history, not just the working tree
gitleaks detect --source . --redact --report-format sarif --report-path gitleaks.sarif
trufflehog git file://. --no-verification --fail --json | jq 'del(.Raw, .RawV2)' > /secure/path/th.json
# IaC / container
checkov -d . --compact ; trivy config .
```
Four rules about the tooling:
**Exit codes are per-tool, and several default to 0 with findings.** Verify each one's documented
contract and gate on it explicitly. `osv-scanner` exit **128 is a hard failure of the audit itself** —
treating it as a pass means you shipped on a scan that never ran. `bandit`'s `-c pyproject.toml` errors
if the file has no `[tool.bandit]` table, so a repo without that section needs the flag dropped, not
added.
**Record what was actually scanned.** Every scan's evidence entry needs the count of packages or files
examined. A misconfigured scan that examined nothing produces a clean report indistinguishable from a
secure codebase.
**Scanners exfiltrate.** `semgrep --config=auto` and registry packs fetch rules and send metrics; use
pinned local rules and `--metrics=off` for confidential code, and `osv-scanner --offline
--offline-vulnerabilities` with a pre-downloaded database when the dependency list itself is sensitive.
**`trufflehog` verification mode authenticates with the credentials it finds** — real outbound requests
using live secrets. Use `--no-verification` for the inventory pass; `--results=verified` only with
written scope naming verification as permitted, and tell whoever watches the logs first. Never write
its JSON into the repo tree, and strip `.Raw`/`.RawV2` before any human sees or stores it.
**Active scanning (ZAP, nuclei) only against an authorized non-production target**, and never as a
default step.
Then triage: reachability beats raw severity, and a CVE in a dev-only dependency that never ships is
not the same finding as one in the shipped artifact. Say which is which.
## Step 7 — Compliance Readiness, Honestly
For each framework in scope, **read the current criteria from the authoritative source at audit time**
rather than reciting identifiers from memory, then classify every control:
| Verdict | Meaning |
|---|---|
| **Evidenced in code** | The control exists and you can point to it — file, config, or CI job |
| **Partially evidenced** | Present but incomplete or inconsistently applied |
| **Not evidenced** | Applicable, absent |
| **Not answerable from a repository** | Organizational — HR onboarding and offboarding, vendor management, physical security, policy documents, board oversight, incident-response process, background checks, training |
That last row is the honest half, and it is usually the larger half. Say so plainly: a repository can
speak to change management, access control, encryption in transit and at rest, logging and monitoring,
vulnerability management, and secure development practices. It cannot speak to whether offboarding
actually revokes access, whether vendors were assessed, or whether anyone reviewed the policy.
Where the code *can* provide evidence, name the artifact an auditor would accept: branch protection
settings, required reviews, CI gates, the dependency-scanning job, encryption configuration, log
retention, access-control tests.
**Never output the words "compliant", "certified", or "passing" about a framework.** The output is
readiness, gaps, and the evidence you can hand an auditor.
## Step 8 — The Report
Write to `.audit/security-report.md` — and treat it as sensitive (see Handling).
Per finding:
```
id · title · severity (with the reasoning, not just a label) · CWE where it applies
location: file:line, or endpoint + method
precondition: what an attacker needs (unauthenticated? a free account? a specific role?)
reproduction: the minimal concrete steps
impact: what is actually reachable — data, funds, privilege
remediation: the specific change, not "validate input"
verification: the test that proves it fixed
```
Order by **exploitability and impact**, not by scanner severity. An unauthenticated IDOR exposing
customer records outranks a dozen medium-severity dependency advisories in code that never executes.
Separate the compliance-readiness section, with the four-way verdict per control and a clear statement
of scope and method.
Open with a **scope, methodology and coverage** section: what was reviewed and how, the population
covered (which branches, which commit, which environments), what each tool examined and how many
items it actually saw, what was skipped, and what could not be verified without an environment you did
not have. Name which classes have no automated coverage.
**State which team passes ran, and which did not.** A reader cannot calibrate a report without it: an
audit with no Red pass has not tested exploitability, one with no Blue pass says nothing about
detection, and one with no Black pass has not looked at the supply chain or the human path. List the
seats exercised, the seats declined, and for each declined one whether it was out of scope, unauthorized,
or simply not done.
Close the loop on lifecycle: every finding needs a state — open, fixed, or **risk-accepted with an
owner and a date**. A finding nobody accepted and nobody fixed is still open, and silently dropping it
between runs is how a report becomes fiction.
## Step 9 — Then Ask
**Present the report and ask what to fix.** Do not start editing.
Offer, in order:
1. **Critical and exploitable now** — recommend fixing these immediately, one at a time, with a
regression test per fix that fails before and passes after.
2. **Structural** — an access-control pattern applied in one place should be applied at a chokepoint;
propose the refactor rather than patching each caller.
3. **Hygiene** — dependency bumps, header hardening, lint rules that prevent recurrence.
4. **Compliance gaps** with a code answer — CI gates, branch protection, logging, encryption config.
For each fix applied: verify it, and **add the check that prevents recurrence** — a test, a CI gate, a
lint rule. A security fix without a gate returns.
## Handling The Report
A document describing live, exploitable vulnerabilities is one of the most sensitive artifacts a
project has.
- **Never commit it to a public repository**, and never paste findings into a public issue, PR, or chat.
- Keep it out of the working tree if the repo is public — write it somewhere gitignored and say where.
- Do not put reproduction detail for an unfixed vulnerability into any tracker that is not private.
- Redact credentials, tokens and customer data from every excerpt.
- When a finding is fixed and released, the detail can be shared; before that it is a weapon.
If findings involve customer data exposure, note that breach-notification obligations may have clocks
attached, and that determination belongs to counsel — flag it, do not adjudicate it.
## Rationalization Table
| Excuse | Reality |
|---|---|
| "We ran the audit" | From which seats? An audit with no Blue pass says nothing about whether you would notice |
| "No detections fired, so nothing happened" | Or nothing is instrumented. Blue's first finding is usually that there is nothing to look at |
| "Red found it, and we fixed it" | Half done. Purple asks for the detection and the regression test; Orange asks what stops the class |
| "The scan came back clean" | Scanners barely find access-control bugs. That is the class that gets exploited |
| "We're SOC 2 compliant now" | An audit firm says that after examining the organization. This is readiness |
| "The UI hides it from free users" | Hidden is not disabled. Call the endpoint |
| "The client checks the license" | Then the user controls the license. Gate the data server-side |
| "The API key is only in the mobile app" | The binary is readable. That key is public |
| "It's behind login, so it's fine" | Authentication is not authorization. Check object ownership |
| "It's an internal endpoint" | Verify that claim from the network config, not the name |
| "I'll run ZAP against prod to be thorough" | Never. Authorized non-production targets only |
| "That CVE is in a dev dependency" | Then say so and rank it accordingly — but confirm it does not ship |
| "I'll open an issue with the repro" | Not in a public tracker for an unfixed vulnerability |
| "Severity is medium, the scanner said so" | Rank by exploitability and impact in *this* system |
| "The scan passed" | Check it scanned anything. Record the count of files and packages examined |
| "Non-zero exit, probably a tool glitch" | osv-scanner 128 means the audit did not run. Fail closed |
| "I'll cite A01 for this" | Name the edition — A01:2025. A bare code is ambiguous across editions |
| "We want a SOC 2 report for the website" | SOC 2 is restricted-use. The public one is SOC 3 |
| "We can fix it later, it's theoretical" | Then demonstrate it is unreachable. Otherwise it is a finding |
## Red Flags — Stop
- Using the words "compliant" or "certified" about any framework
- Running an active scan without explicit authorization for that specific target
- Pointing any scanner at production
- Sampling routes for access control instead of enumerating all of them
- Reciting a framework criterion id or OWASP category code without checking the current edition, or
citing an OWASP category without its edition year
- Combining a report-narrowing filter with a gating flag in the same scanner run
- Reporting a clean scan without recording how many files or packages it actually examined
- Committing the findings report to a public repo, or putting a repro in a public issue
- A CI security gate that continues on a non-zero exit
- `trufflehog` with verification enabled against credentials you did not intend to test
- Fixing anything before the user has seen the report and chosen
- Declaring a fix done without a regression test and a gate against recurrence
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!