security-audit-light
Skill2 starsChanged 3 months agoMITView on GitHub
Perform a PR-scoped security audit on a small to medium code change (1-20 files, additive endpoint, schema change, refactor). Produces a structured findings table with confidence scores, no false positives, and a clean verdict. Trigger only when the user explicitly asks for a "security audit", "security review", "vulnerability check", "is this safe to ship", or "OWASP check" of recent changes. NOT for greenfield threat modeling, full-codebase reviews, or infrastructure audits — those need heavier tooling. NOT for proactive scanning while writing code.
In this repository53 other files it gives its agents.
- instructions/AGENTS.mdAGENTS.md
- skills/software-development/php-best-practices/AGENTS.mdAGENTS.md
- instructions/CLAUDE.mdCLAUDE.md
- architecture-designerSkill
- caveman-commitSkill
- caveman-compressSkill
- cavemanSkill
- conventional-commitSkill
- youtube-contentSkill
- agentkit-skill-authoringSkill
- skill-orchestrationSkill
- analogical-thinkingSkill
- investigateSkill
- ponytailSkill
- systematic-debuggingSkill
- mermaid-diagramsSkill
- feature-forgeSkill
- find-skillsSkill
- impeccableSkill
- javascript-proSkill
- legacy-modernizerSkill
- migrationSkill
- no-ai-slopSkill
- olakunlevpn-filament-skillsSkill
- clickupSkill
- clickup-tweak-workflowSkill
- git-advancedSkill
- local-wikiSkill
- mr-reviewSkill
- php-proSkill
- doxSkill
- improveSkill
- openspecSkill
- scrutinizeSkill
- systems-thinkingSkill
- tweakSkill
- tweak-workflowSkill
- prompt-engineerSkill
- laravel-best-practicesSkill
- pest-testingSkill
- php-best-practicesSkill
- security-best-practicesSkill
- spatie-javascriptSkill
- spatie-laravel-phpSkill
- spatie-securitySkill
- spatie-version-controlSkill
- tailwindcss-developmentSkill
- test-driven-developmentSkill
- sql-proSkill
- typescript-proSkill
- ui-ux-pro-maxSkill
- vue-expert-jsSkill
- vue-expertSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 5 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 27
Read top-level config files to confirm framework, then declare scope explicitly:
- Very specific: line 66
Framework-meta rule: when the symbol is generated by ORM/framework metaclass (Eloquent scope, Django Meta, Rails has_many, Laravel …
- Distinctive: line 106
If the user says they shipped a fix, re-read the changed file and re-run steps 2-5 scoped to the fix.
- Distinctive: line 110
"No findings" without coverage statement: if your attack surface census shows zero rows, you didn't audit — you just said "looks safe".
- Distinctive: line 112
Reusing scope from a previous audit: if the user asks for a NEW audit, do not reuse conclusions from a previous one without re-verifying.
- Distinctive: line 156
When the audit is clean, keep the output short.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Security Audit (Light)
PR-scoped security audit distilled from CSO's methodology. Optimized for additive endpoints, schema changes, small refactors. Single-prong — read the diff, verify each finding end-to-end, output a verdict. No subagent fan-out, no infrastructure passes, no telemetry.
When to use
- User says "security audit", "security review", "OWASP check", "is this safe", "anything fishy?"
- Scope is the current branch / latest uncommitted changes (1-20 files)
- Stack is one of: PHP/Laravel, Python/Django/FastAPI, Node/Express/Nest, Ruby/Rails, Go/Gin, Java/Spring Boot, Rust/Axum
When NOT to use
- Greenfield (no code yet) → use
systematic-debuggingor another skill - User asks for full codebase audit → this skill is PR-scoped by design
- User wants proactive scanning while writing code → defer to
security-best-practices - Audit depends on infrastructure (CI/CD, deploy pipeline, secrets manager) → out of scope
Procedure
Step 1 — Detect stack + scope (30 seconds)
Read top-level config files to confirm framework, then declare scope explicitly:
| Field | Source | Example |
| Stack | composer.json, package.json, pyproject.toml, etc. | Laravel 12 / PHP 8.4 |
| Scope | git diff --stat <baseline>..HEAD | 5 files, 202 insertions |
| Branch | git branch --show-current | feat/GYMED-793 |
| Baseline SHA | git rev-parse --short HEAD~1 (or merge-base) | 79d68ef |
State scope in the output: "Auditing 5 files / 202 insertions on feat/X since <sha>."
Step 2 — Attack surface census (1 minute)
Build a tiny table covering what an attacker can touch. For each row, name the file:line or write none.
ATTACK SURFACE CENSUS
AuthN entry points: N (e.g. auth:api middleware — routes/api.php:25)
Authorization gates: N (e.g. abort_unless isProfessional — DashboardController.php:89)
Cross-tenant scoping: N (e.g. sessionsForProfessionalStudents — Service.php:140)
User-supplied inputs: N (e.g. filter[status], pain_level, rpe)
Output resource fields: N (e.g. DashboardSessionPreviewResource)
Storage mutation paths: N (e.g. markAsReviewed, store, update)
Pagination cursors: N (e.g. cursorPaginate(15))
Sensitive field loads: N (e.g. user selects [..., email, ...])This forces you to declare coverage before claiming "clean". If a row is none, you've just decided it's out of scope — make that decision visible.
Step 3 — Pre-emit verification gate (the "1539 rule")
For every potential finding, BEFORE writing it:
- Quote the verbatim code that motivates it with
file:line. Not a paraphrase — the exact text. - Trace it end-to-end: from input (Request / user / external caller) to output (Query / Response / file). Confirm the path exists, not just the pattern.
- Confirm the mitigating code exists by quoting it (e.g. the validator rule, the authorization check, the scope-bypass).
If you cannot quote the motivating line, drop the finding's confidence to 4-5 (suppressed from main report, go to appendix only). Do not invent confidence to pass the gate.
Framework-meta rule: when the symbol is generated by ORM/framework metaclass (Eloquent scope, Django Meta, Rails has_many, Laravel withoutGlobalScope), quote the meta-construct or migration — don't expect the literal name in the class body.
Step 4 — Confidence calibration (1-10)
| Score | Meaning | Display |
| 9-10 | Verified by reading specific code, concrete exploit demonstrated | Main report |
| 7-8 | High confidence, very likely correct | Main report |
| 5-6 | Could be FP, verify with author | Main report with caveat |
| 3-4 | Suspicious but possibly fine | Suppressed — appendix only |
| 1-2 | Speculation | Only if severity is P0 |
Step 5 — Output format
Finding format:
[Px] (confidence: N/10) file:line — one-sentence descriptionSeverity scale (priority = exploitability × blast radius):
| Code | Meaning |
| P0 | Critical, ship-blocker, immediate exploit |
| P1 | High, ship after fix |
| P2 | Medium, plan a fix |
| P3 | Low, opportunistic / hardening |
| P4+ | Cosmetic / advisory |
Final structure:
- Scope (1 line): branch, commit baseline, files changed
- Stack (1 line)
- Attack surface census (small table)
- Trust boundaries re-verified (table — "no new findings" rows OK)
- Findings (table:
[Px] (N/10) file:line — description) — empty table if clean - Verdict: APPROVED / APPROVED WITH NITS / BLOCKED with one-line reason
Step 6 — Re-audit if anything changes
If the user says they shipped a fix, re-read the changed file and re-run steps 2-5 scoped to the fix. Do NOT just accept "fixed it" — verify end-to-end the same way you verified the original finding.
Pitfalls
- "No findings" without coverage statement: if your attack surface census shows zero rows, you didn't audit — you just said "looks safe". Always emit the census, even if every row is "none".
- Pattern-match FPs (the FP class CSO calls "1539"): "field X doesn't exist" requires quoting the model body; "dict.get() might be None" requires quoting the dict init. If you find yourself writing "this could be a problem if X", stop and go read the X.
- Reusing scope from a previous audit: if the user asks for a NEW audit, do not reuse conclusions from a previous one without re-verifying. Each audit is its own evidence chain.
- Severity inflation: a missing CSRF token on an internal admin tool is not P0. Calibrate by exploitability × blast radius, not by vibes.
- Skipping the user-supplied-input trace: most security bugs in PRs are at the input boundary (no validation, wrong scope, wrong auth). Always trace each query/body parameter from
RequesttoEloquent/QueryBuilder/fetch. - Listing what you DIDN'T audit as if it were clean: "no SQL injection found" is a claim. State the scope ("did not audit migrations", "did not audit infrastructure") separately.
Verification steps
- Scope declared in opening line
- Attack surface census has ≥5 rows, each with file:line or explicit "none"
- Every finding quotes its motivating code line(s)
- Every finding has a confidence 1-10 score
- Findings at confidence ≤4 are in appendix, not main report
- Final verdict is one of: APPROVED / APPROVED WITH NITS / BLOCKED
- Findings count + verdict fit on one screen for clean audits, or fit on one page for noisy ones
- Did-not-audit scope is stated separately from clean findings
Output template (copy-paste starter)
## Security audit — <branch> / <baseline-sha> → <head-sha>
**Stack**: <framework> <version>
**Scope**: <N> files, <N> insertions on `<branch>` since `<sha>`
**Method**: pre-emit verification gate + 1-10 confidence
### Attack surface census
| Boundary | Where | File:line |
|---|---|---|
| AuthN | <gating middleware/group> | <file>:<line> |
| AuthZ | <gate> | <file>:<line> |
| Cross-tenant scoping | <helper> | <file>:<line> |
| User-supplied inputs | <list, e.g. filter[status], page cursor> | <file>:<line> |
| Output resource | <resource class> | <file>:<line> |
| Sensitive field loads | <list, e.g. user selects> | <file>:<line> |
### Findings
| # | Finding | Severity | Confidence | Evidence |
|---|---|---|---|---|
| — | (none) | — | — | — |
### Verdict
**APPROVED** — <one-line summary of why, e.g. "additive endpoint reuses pre-audited scope chain; filter input whitelisted; no PII leakage in response.">When the audit is clean, keep the output short. Length scales with findings, not with repo size.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

