/auditing-code-for-vulnerabilities
Audit source code for exploitable vulnerabilities using threat-model-driven review, taint tracing, invariant checking, and variant analysis. Use when reviewing a codebase or diff for security bugs, performing a security audit, hunting for vulnerabilities in a target's source, or
$ npx -y skills add trilwu/secskills --skill auditing-code-for-vulnerabilities --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/auditing-code-for-vulnerabilities
Context preview
The summary Claude sees to decide when to auto-load this skill.
Audit source code for exploitable vulnerabilities using threat-model-driven review, taint tracing, invariant checking, and variant analysis. Use when reviewing a codebase or diff for security bugs, performing a security audit, hunting for vulnerabilities in a target's source, or
SKILL.md
auditing-code-for-vulnerabilities.SKILL.mdname: auditing-code-for-vulnerabilities
description: Audit source code for exploitable vulnerabilities using threat-model-driven review, taint tracing, invariant checking, and variant analysis. Use when reviewing a codebase or diff for security bugs, performing a security audit, hunting for vulnerabilities in a target's source, or validating whether a suspected finding is real.
verified: 2026-07-28
Auditing Code for Vulnerabilities
Finding real bugs in source code is a different job from running a scanner. A scanner matches patterns; an auditor builds a model of what the code is *supposed* to guarantee and then hunts for the paths where that guarantee breaks. This skill is the methodology for the second job.
When to Use
- Auditing a repository, service, or library for security defects
- Reviewing a diff, branch, or pull request for introduced vulnerabilities
- Hunting for a specific bug class across a large codebase
- Validating whether a scanner finding or a reported vulnerability is real
- Building an audit plan and coverage report for a client engagement
When NOT to Use
- **Black-box testing of a running app** — use `testing-web-applications` or `testing-apis`
- **A PHP codebase specifically** (type juggling, unserialize/phar POP chains, php:// wrappers) — this methodology plus `auditing-php-applications`
- **Hunting a planted webshell or backdoor** rather than a vulnerability — use `hunting-web-backdoors`
- **Binary-only targets** — use `analyzing-binaries`
- **Dependency and build-pipeline risk** — use `auditing-supply-chain`
- **Cryptographic construction review** — use `reviewing-cryptography`
- **Writing up finished findings** — use `reporting-security-findings`
- **Running a multi-agent discovery campaign** across a whole target with
builder/critic separation and iteration — use `orchestrating-vulnerability-research`, which dispatches *this* skill as the per-slice hunter
The Loop
Auditing is four passes, not one. Do not skip to pass 3.
1. Context → what does this system protect, and from whom?
2. Attack surface → where does untrusted input enter, and what does it reach?
3. Hunt → trace specific bug classes along those paths
4. Verify → prove exploitability before you write a word
Pass 1: Build context before reading code
Do not open files at random. Spend the first block of effort answering:
| Question | Where to look | | --- | --- | | What are the security-relevant assets? | README, docs, data models, DB schema | | Who are the actors and trust tiers? | Auth middleware, role enums, tenant models | | What are the stated invariants? | Tests, assertions, comments containing "must", "never", "invariant" | | What has already been fixed here? | `git log --grep` for security keywords, CVE files, SECURITY.md | | What is out of scope? | Engagement brief, vendor code, generated files |
# Prior security work is the cheapest source of bug leads
git log --oneline --grep='security\|CVE\|vuln\|injection\|auth bypass\|overflow' -i | head -40
# Stated invariants often mark where the author was nervous
rg -n --stats 'MUST NOT|must never|SECURITY|XXX|HACK|TODO.*(auth|secur|valid)' -i
# Where does privilege actually get checked?
rg -n 'is_admin|require_role|authorize|has_permission|@login_required|checkAccess'
Write a short target model before hunting: assets, actors, trust boundaries, and the three invariants whose violation would matter most. Everything after this is a search for counterexamples to those invariants.
Pass 2: Map the attack surface
Enumerate *entry points*, then rank them. An entry point matters in proportion to how far it reaches before it is validated.
# HTTP/RPC routes
rg -n '@(app|router)\.(get|post|put|delete|patch)|app\.(get|post)\(|@RequestMapping|http\.HandleFunc'
# Deserialization, template rendering, and dynamic execution sinks
rg -n 'pickle\.loads|yaml\.load\(|Marshal|unserialize|ObjectInputStream|eval\(|new Function|exec\(|Runtime\.getRuntime'
# Command, SQL, and path sinks
rg -n 'os\.system|subprocess.*shell\s*=\s*True|child_process\.exec\(|execSync|Statement\.execute|\.raw\(|fmt\.Sprintf.*SELECT'
# Where authentication is decided rather than enforced
rg -n 'verify=False|InsecureSkipVerify|jwt\.decode\(.*verify.*False|algorithms=\[.*none'
Rank entry points by: reachable without authentication > reachable by a low privilege tier > reachable only by an admin. Then follow the highest-ranked ones inward. Depth beats breadth — one fully traced path is worth twenty grep hits.
**Grep hits are candidates, not findings.** The commands above are a cheap wide net; each match is an unresolved lead until you have traced it. Persist the candidate set — a worklist of `(file:line, bug class, entry point)` — and drive every entry to an explicit verdict: *traced-safe*, *confirmed*, or *needs-PoC*. Widen the net cheaply, then spend expensive reasoning per candidate — never the reverse. The failure mode is not a missing grep pattern; it is enumerating fifty candidates, eyeballing five, and calling the tree clean. On a large codebase, fold the project's own conventions into the net — its ORM's raw-query escape hatch, its auth decorator's name, its templating call — because the highest-yield sinks are the ones generic patterns miss.
Pass 3: Hunt bug classes along the traced paths
For each promising path, trace taint from source to sink and ask what the code assumes. The high-yield classes, in rough order of how often they survive to production:
**Authorization, not authentication.** Most real breaches are missing object level checks, not broken login. For every handler that takes an ID, ask: is the object scoped to the caller's tenant/user, or only looked up by ID? Check the query, not the decorator.
**Trust-boundary confusion.** Data validated at one layer and re-parsed at another. Look for values that cross a serialization boundary — a validated string re-parsed as a URL,
Read more
name: auditing-code-for-vulnerabilities description: Audit source code for exploitable vulnerabilities using threat-model-driven review, taint tracing, invariant checking, and variant analysis. Use when reviewing a codebase or diff for security bugs, performing a security audit, hunting for vulnerabilities in a target's source, or validating whether a suspected finding is real. verified: 2026-07-28
Auditing Code for Vulnerabilities
Finding real bugs in source code is a different job from running a scanner. A scanner matches patterns; an auditor builds a model of what the code is *supposed* to guarantee and then hunts for the paths where that guarantee breaks. This skill is the methodology for the second job.
When to Use
- Auditing a repository, service, or library for security defects
- Reviewing a diff, branch, or pull request for introduced vulnerabilities
- Hunting for a specific bug class across a large codebase
- Validating whether a scanner finding or a reported vulnerability is real
- Building an audit plan and coverage report for a client engagement
When NOT to Use
- **Black-box testing of a running app** — use `testing-web-applications` or `testing-apis`
- **A PHP codebase specifically** (type juggling, unserialize/phar POP chains, php:// wrappers) — this methodology plus `auditing-php-applications`
- **Hunting a planted webshell or backdoor** rather than a vulnerability — use `hunting-web-backdoors`
- **Binary-only targets** — use `analyzing-binaries`
- **Dependency and build-pipeline risk** — use `auditing-supply-chain`
- **Cryptographic construction review** — use `reviewing-cryptography`
- **Writing up finished findings** — use `reporting-security-findings`
- **Running a multi-agent discovery campaign** across a whole target with
builder/critic separation and iteration — use `orchestrating-vulnerability-research`, which dispatches *this* skill as the per-slice hunter
The Loop
Auditing is four passes, not one. Do not skip to pass 3.
1. Context → what does this system protect, and from whom? 2. Attack surface → where does untrusted input enter, and what does it reach? 3. Hunt → trace specific bug classes along those paths 4. Verify → prove exploitability before you write a word
Pass 1: Build context before reading code
Do not open files at random. Spend the first block of effort answering:
| Question | Where to look | | --- | --- | | What are the security-relevant assets? | README, docs, data models, DB schema | | Who are the actors and trust tiers? | Auth middleware, role enums, tenant models | | What are the stated invariants? | Tests, assertions, comments containing "must", "never", "invariant" | | What has already been fixed here? | `git log --grep` for security keywords, CVE files, SECURITY.md | | What is out of scope? | Engagement brief, vendor code, generated files |
# Prior security work is the cheapest source of bug leads git log --oneline --grep='security\|CVE\|vuln\|injection\|auth bypass\|overflow' -i | head -40 # Stated invariants often mark where the author was nervous rg -n --stats 'MUST NOT|must never|SECURITY|XXX|HACK|TODO.*(auth|secur|valid)' -i # Where does privilege actually get checked? rg -n 'is_admin|require_role|authorize|has_permission|@login_required|checkAccess'
Write a short target model before hunting: assets, actors, trust boundaries, and the three invariants whose violation would matter most. Everything after this is a search for counterexamples to those invariants.
Pass 2: Map the attack surface
Enumerate *entry points*, then rank them. An entry point matters in proportion to how far it reaches before it is validated.
# HTTP/RPC routes rg -n '@(app|router)\.(get|post|put|delete|patch)|app\.(get|post)\(|@RequestMapping|http\.HandleFunc' # Deserialization, template rendering, and dynamic execution sinks rg -n 'pickle\.loads|yaml\.load\(|Marshal|unserialize|ObjectInputStream|eval\(|new Function|exec\(|Runtime\.getRuntime' # Command, SQL, and path sinks rg -n 'os\.system|subprocess.*shell\s*=\s*True|child_process\.exec\(|execSync|Statement\.execute|\.raw\(|fmt\.Sprintf.*SELECT' # Where authentication is decided rather than enforced rg -n 'verify=False|InsecureSkipVerify|jwt\.decode\(.*verify.*False|algorithms=\[.*none'
Rank entry points by: reachable without authentication > reachable by a low privilege tier > reachable only by an admin. Then follow the highest-ranked ones inward. Depth beats breadth — one fully traced path is worth twenty grep hits.
**Grep hits are candidates, not findings.** The commands above are a cheap wide net; each match is an unresolved lead until you have traced it. Persist the candidate set — a worklist of `(file:line, bug class, entry point)` — and drive every entry to an explicit verdict: *traced-safe*, *confirmed*, or *needs-PoC*. Widen the net cheaply, then spend expensive reasoning per candidate — never the reverse. The failure mode is not a missing grep pattern; it is enumerating fifty candidates, eyeballing five, and calling the tree clean. On a large codebase, fold the project's own conventions into the net — its ORM's raw-query escape hatch, its auth decorator's name, its templating call — because the highest-yield sinks are the ones generic patterns miss.
Pass 3: Hunt bug classes along the traced paths
For each promising path, trace taint from source to sink and ask what the code assumes. The high-yield classes, in rough order of how often they survive to production:
**Authorization, not authentication.** Most real breaches are missing object level checks, not broken login. For every handler that takes an ID, ask: is the object scoped to the caller's tenant/user, or only looked up by ID? Check the query, not the decorator.
**Trust-boundary confusion.** Data validated at one layer and re-parsed at another. Look for values that cross a serialization boundary — a validated string re-parsed as a URL,
**Security skills for Claude Code that encode the judgment professionals bring, not another wrapper around a scanner.** Offense, defense, and the reverse-engineering and code-audit core both sides share. Every skill is fact-checked against primary sources.

