Security audit — vulnerability scan, pentest review, attack-surface sweep; explicit request only, not regular feature work. Pre-implementation threat pass → threat-modeling.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add event4u-app/agent-config --skill security-audit --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Security Audit?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/event4u-app-security-audit-agent-config)More formats (shields.io, HTML) on the badges page.
---
model_tier: high
name: security-audit
description: "Security audit — vulnerability scan, pentest review, attack-surface sweep; explicit request only, not regular feature work. Pre-implementation threat pass → threat-modeling."
domain: quality
parallelizable: files
workspaces:
- engineering
packs:
- engineering-base
---
# security-audit
## Mission
Find real security vulnerabilities in code before they are exploited. This skill is
**proactive** — it audits code for security weaknesses, not just responds to incidents.
For writing secure code patterns (policies, auth, CSRF), use the `security` skill instead.
## When to use
Use this skill when:
- Auditing a codebase or module for security risks
- `analysis-autonomous-mode` routes here after detecting risky patterns
- Reviewing code that handles user input, authentication, or authorization
- Checking for vulnerabilities before a release or deployment
Do NOT use when:
* Writing new auth/policy code — route to [`security`](../security/SKILL.md)
* Hunting for functional bugs — route to [`bug-analyzer`](../bug-analyzer/SKILL.md) (proactive mode)
* Investigating performance — route to [`performance-analysis`](../performance-analysis/SKILL.md)
* You need a pre-implementation threat model for a new feature — route to
[`threat-modeling`](../threat-modeling/SKILL.md)
* You need end-to-end authorization analysis for one route/action — route to
[`authz-review`](../authz-review/SKILL.md)
## Procedure: Security audit
### 0. False-positive gate — restate the claim before reporting
Before any finding enters the report, restate it as one falsifiable sentence
naming all three of:
1. **Privilege level** — what access the attacker already has (anonymous,
authenticated user, tenant admin, CI runner).
2. **Execution context** — where the vulnerable code runs (request handler,
queue worker, sandboxed template, build step).
3. **Attacker precondition** — the concrete state or input the attacker must
control to trigger it.
If any of the three cannot be named concretely, the item is **not a finding
yet** — trace further or drop it with a one-line reason.
**Rationalizations to Reject:**
| Rationalization | Reality |
|---|---|
| "It looks dangerous" | Pattern-recognition is not analysis — trace the full data flow from entry to sink first |
| "This is clearly critical" | Complete a devil's-advocate pass — models systematically overrate severity |
| "Report it just in case" | Over-reporting erodes trust; an unverifiable finding is noise, not diligence |
| "Same pattern as a known CVE" | Same pattern ≠ same preconditions — verify the preconditions hold in THIS codebase |
**Standard vs. Deep verification routing:**
- **Standard** — traced data flow + all three claim elements named → report
with the normal field list.
- **Deep** — severity would be High/Critical, OR the precondition chain
crosses a trust boundary you did not personally trace → run a
devil's-advocate pass first: actively try to refute the finding (existing
middleware? framework default? type system? config?). Report only what
survives; findings the pass killed are listed one-line under
*Rejected candidates* so the triage is auditable.
### 1. Map attack surface
Identify all entry points where untrusted data enters:
- HTTP request parameters, headers, cookies
- File uploads
- API payloads (JSON, XML, form data)
- Webhook callbacks
- Queue job payloads from external sources
- Import files (CSV, Excel, XML)
- URL path segments and query strings
### 2. Trace trust boundaries
For each entry point, trace where user input flows:
```
User Input → Controller → Validation → Service → DB/File/External
↓ ↓ ↓
Is it sanitized? Complete? Used safely?
```
### 3. Check vulnerability categories
| Category | What to look for |
|---|---|
| **SQL Injection** | Raw queries with concatenation, missing parameter binding |
| **XSS** | Unescaped template output (Blade `{!! !!}`, JSX `dangerouslySetInnerHTML`, Jinja `|safe`), JSON responses with HTML |
| **CSRF** | Missing middleware, API endpoints without token verification |
| **Auth bypass** | Missing policy checks, broken gate logic, `withoutMiddleware()` |
| **IDOR** | Direct object access without ownership verification |
| **Mass assignment** | Missing `$fillable`/`$guarded`, `request()->all()` in create/update |
| **File upload** | Missing type validation, path traversal, executable uploads |
| **SSRF** | User-controlled URLs passed to HTTP client |
| **Deserialization** | Unserializing user input, unsafe queue payloads |
| **Secret exposure** | Hardcoded credentials, secrets in logs, `.env` in public dir |
| **Rate limiting** | Missing throttle on auth endpoints, password reset, API |
| **Header injection** | User input in response headers, email headers |
| **Insecure defaults / fail-open** | Guards that allow on error (`catch { return true }` in an authz check), default-allow matchers, debug mode defaulting on, permissive CORS/`verify=false` fallbacks, feature flags whose missing value grants access |
Worked example (fail-open): `if (!$gate->check($user)) { … }` wrapped in a
`try/catch` that logs and **continues** fails open — an exception in the gate
grants access. Finding shape: Category *Insecure defaults*, Evidence the
catch block `file:line`, Fix *fail closed — rethrow or deny on gate error*.
### 3b. Out of scope — route, do not guess
The table above names vulnerability **classes**, which are stable. This package
carries no cryptographic parameter, key size, work factor, cipher suite, or TLS
version floor: a value copied here reads authoritative long after it stops being
true. Report the finding, route the fix to
<https://cheatsheetseries.owasp.org/> — Cryptographic Storage, Transport Layer
Security, Password Storage, XML External Entity Prevention — and never name a
value from memory. Rationale and reopening condition:
[ADR-238](../../../docs/decisions/ADR-238-security-content-routes-to-external-authority.md).
### 4. Framework-specific checks
→ Laravel-specific checks: see [`laravel`](../laravel/SKILL.md) § Security audit checks.
### 5. Dependency audit
- Check `composer.lock` for known vulnerable packages
- Check `package-lock.json` for frontend vulnerabilities
- Identify outdated packages with known CVEs
- Check if security patches are available
## Output format
1. Emit one entry per vulnerability using the field list below; one finding = one block, never merge.
2. Category must map to an OWASP Top 10 (or LLM Top 10) bucket; Severity must use Low / Medium / High / Critical with a single Exploitability tag.
3. Close with a *Recommended Fix Order* ranked by exploitability × blast radius and tag each line with Confidence.
For each vulnerability:
- **Vulnerability:** concise title
- **Category:** OWASP category (Injection, Broken Auth, etc.)
- **Location:** file and line
- **Severity:** Low / Medium / High / Critical
- **Exploitability:** How easy to exploit (trivial / requires auth / complex)
- **Impact:** What an attacker could achieve
- **Evidence:** code reference showing the weakness
- **Fix:** concrete mitigation
- **Confidence:** Low / Medium / High
After the findings, add a **Rejected candidates** section: one line per
look-dangerous-but-benign pattern the Step-0 gate killed, with the traced
reason ("raw SQL string is a static migration constant — no user input
reaches it"). An audit that rejects nothing has usually skipped the gate.
## Integration with other skills
- **analysis-autonomous-mode** — routes here when security concerns are detected
- **security** — complementary: security is about writing secure code, this is about finding holes
- **universal-project-analysis** — provides context about packages and framework usage
- **bug-analyzer** — some bugs have security implications (chain when found)
- **untrusted-input-defense** / **lethal-trifecta-guard** (rules) — prompt-injection / agent-config defense; consult when the audited code ingests untrusted content or wires an autonomous egress path
## Gotcha
- Don't report theoretical vulnerabilities without a concrete attack vector — false positives erode trust.
- The model tends to flag framework-handled security as issues (e.g., Laravel's CSRF or Rails' `protect_from_forgery` is already handled).
- Always check if a finding is already mitigated by middleware or configuration before reporting it.
## Do NOT
- Do NOT report theoretical risks that require impossible preconditions
- Do NOT ignore user input flows — always trace from entry to usage
- Do NOT assume frameworks handle everything — verify middleware and config
- Do NOT confuse code quality issues with security vulnerabilities
- Do NOT skip dependency checking — known CVEs are real risks
## See also
- [`docs/threat-model.md`](../../../docs/threat-model.md) — package attack surface and trust boundary documentation.
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!