| name | security-audit |
| description | OWASP-guided security code review for a specific domain or issue |
| argument-hint | <issue-number|domain> |
| user-invocable | true |
Security Audit
Perform a structured, OWASP-guided security code review for a specific security domain. Designed to work with security epic sub-issues — reads the issue to understand what domain to audit, then systematically scans the codebase and produces a structured report.
Input
$ARGUMENTS — either a GitHub issue number (e.g., 631) or a security domain keyword.
Supported domains:
dependencies — Dependency vulnerability audit (npm + pip)
auth — Authentication & authorization review
input-validation — OWASP Top 10 input validation (SQLi, XSS, SSRF, etc.)
file-uploads — File upload security review
headers — HTTP security headers audit
rate-limiting — Rate limiting review
database — Database security review
infrastructure — Infrastructure, secrets, Docker, session security
pentest — OWASP ZAP baseline scan
ci-cd — CI/CD pipeline and GitHub Actions security review
If a number is provided, fetch the issue and infer the domain from its title/body.
Phase 1: Determine Scope
If $ARGUMENTS is a number:
~/.claude/bin/gh-save.sh /tmp/security-audit-$ARGUMENTS.json issue view $ARGUMENTS --json title,body,labels
Read the file and determine which domain to audit from the issue content.
If $ARGUMENTS is a domain keyword:
Use it directly.
Phase 2: Execute Domain-Specific Audit
Each domain has a specific audit procedure. Follow the relevant one below.
Domain: dependencies
- Run the automated scanner:
~/.claude/bin/deps-audit.sh
- Read the output and categorize findings by severity.
- For each critical/high vulnerability, check if the package is actually used in a reachable code path (not just a transitive dependency).
Report sections: Findings table, remediation steps, accepted risks (if any).
Domain: auth
Systematic code review of authentication and authorization:
- Find auth files: Use Glob for
**/auth/**, **/security.*, **/middleware.*, **/dependencies.*
- JWT review: Read token creation and validation code. Check:
- Algorithm (HS256 is OK for single-service, RS256 for multi-service)
- Token expiration (should be ≤4 hours for access tokens)
- Refresh token handling
- Secret key source (must be from environment, not hardcoded)
- Password handling: Check hashing algorithm (bcrypt/argon2 required, no MD5/SHA1)
- Default-deny posture: Verify authorization defaults to deny:
- New endpoints must require explicit permission grants (not "allow all, then restrict")
- New roles start with zero permissions
- Missing auth decorator = blocked request, not open access
- Permission system: Read permission/role definitions. Check:
- All protected endpoints use auth decorators
- No endpoints accidentally public
- Permission inheritance is correct (higher roles get lower permissions)
- Object-level authorization (IDOR prevention): For every resource endpoint, verify:
- Not just "can user access type X" but "can user access this specific resource"
- Ownership checks:
WHERE user_id = current_user.id
- Test exists: "User A tries to access User B's resource" → must return 403/404
- Privilege escalation: Search for patterns where user input could influence authorization:
- User ID from request body instead of token
- Missing ownership checks on resources
- Role/permission fields in update schemas that should be read-only
Report sections: Auth mechanism summary, findings, risk assessment.
Domain: input-validation
OWASP Top 10 focused review. Verify defense-in-depth: input should be validated at multiple independent layers, so removing one layer does not compromise security.
Layer check (verify each layer is present):
- Layer 1: Type system / schema validation (shape, presence, bounds — e.g., Pydantic, Zod)
- Layer 2: Character / format restrictions (whitelist allowed chars, reject unexpected patterns)
- Layer 3: Explicit security pattern checks (path traversal
.., null bytes, injection patterns)
- Layer 4: Downstream sanitization (parameterized queries, shell-escaping, HTML-encoding)
Specific vulnerability checks:
- SQL Injection:
- Search for raw SQL:
Grep for text(, execute(, raw_connection, .raw(, f"SELECT, f"INSERT, f"UPDATE, f"DELETE
- Verify all queries use ORM or parameterized statements
- XSS:
- Search for
dangerouslySetInnerHTML, innerHTML, document.write
- Check React components for unescaped user input
- Review any server-side HTML rendering
- Command Injection:
- Search for
subprocess, os.system, os.popen, exec(, eval(
- Verify user input never reaches shell commands
- Path Traversal:
- Search for file path construction with user input
- Check for
../ sanitization, os.path.join with user input
- SSRF:
- Search for outbound HTTP requests (
requests.get, httpx, fetch, urllib)
- Check if user input can influence target URLs
Report sections: Per-category findings with file:line references, severity, remediation.
Domain: file-uploads
- Find upload handling: Glob for
**/upload*, **/photo*, **/file*, **/media*
- Read the upload code and check:
- Server-side MIME type validation (not just extension)
- File size limits enforced server-side
- No user-controlled file paths
- Files are processed/re-encoded (not stored raw)
- Storage permissions (files not publicly accessible without auth)
- Image processing library version (Pillow CVEs)
- Run secret scan for any hardcoded storage credentials:
~/.claude/bin/secret-scan.sh
Report sections: Upload flow diagram, validation checks present, gaps found.
Domain: headers
- Check if target is available. Ask the user for the URL if not obvious.
- Run automated header check:
~/.claude/bin/security-headers-check.sh <url>
- Review the application code for where headers could be added:
- Search for middleware configuration in the backend
- Check for existing security header middleware
- Identify the right place to add missing headers
- Generate implementation guidance for missing headers with recommended values.
Report sections: Current header status, missing headers with recommended values, implementation location.
Domain: rate-limiting
- Find existing rate limiting: Grep for
rate_limit, throttle, slowapi, RateLimiter, limiter
- Identify endpoints that need rate limiting:
- Auth endpoints (login, register, forgot-password, verify)
- File upload endpoints
- Search/query endpoints
- Any endpoint that triggers expensive operations (AI, email, payment)
- Check for existing middleware: Read
main.py and middleware configurations
- Assess current coverage: Map which endpoints have limits vs. which need them
Report sections: Current rate limiting map, unprotected critical endpoints, implementation recommendation.
Domain: database
- ORM safety: Verify all database operations use ORM (SQLAlchemy)
- Grep for raw SQL patterns (see input-validation domain)
- Check Alembic migrations for raw SQL that could be vulnerable
- Mass assignment: Check Pydantic schemas for:
- Fields that should be read-only (id, created_at, role) not in update schemas
- No direct
**request.dict() to ORM model without schema validation
- Sensitive data exposure: Check API response schemas for:
- Password hashes never returned
- Internal IDs/tokens not exposed unnecessarily
- Email addresses only returned to the owning user
- Credentials: Verify database connection uses environment variables
Report sections: Query safety assessment, schema review, data exposure check.
Domain: infrastructure
- Run automated scans:
~/.claude/bin/secret-scan.sh
~/.claude/bin/env-audit.sh
~/.claude/bin/docker-audit.sh
- Manual checks:
- HTTPS enforcement configuration
- Session/cookie security flags
- Logging — search for patterns that might log sensitive data (passwords, tokens, PII)
- Error handling — check if error responses leak internal details (stack traces, SQL queries)
Report sections: Automated scan results, manual findings, remediation steps.
Domain: ci-cd
CI/CD pipeline security review focused on GitHub Actions supply chain attacks.
-
Find all workflows:
- Glob for
.github/workflows/*.yml and .github/workflows/*.yaml
- If none found, report "No CI/CD workflows present" and skip remaining checks
-
Pwn Request (CRITICAL): For each workflow, check the trigger event:
pull_request_target with access to secrets = CRITICAL in public repos (allows external PRs to steal secrets)
pull_request_target that checks out PR head (ref: ${{ github.event.pull_request.head.sha }}) and runs untrusted code = CRITICAL
pull_request is safe (forks don't get secret access)
push, workflow_run, workflow_dispatch, schedule are safe (no external trigger)
-
Script injection: Search all workflow files for untrusted input in run: blocks:
${{ github.event.pull_request.title }} — attacker-controlled PR title injected into shell
${{ github.event.pull_request.body }} — attacker-controlled PR body
${{ github.event.issue.title }} — attacker-controlled issue title
${{ github.event.issue.body }} — attacker-controlled issue body
${{ github.event.comment.body }} — attacker-controlled comment
${{ github.head_ref }} — attacker-controlled branch name
- Safe alternative: use environment variables (
env:) or actions/github-script instead of shell interpolation
-
Third-party Actions pinning: Check all uses: references:
uses: actions/checkout@v4 (mutable tag) = MEDIUM — could be replaced by compromised tag
uses: actions/checkout@<full-sha> (pinned hash) = secure
uses: owner/action@main (branch ref) = HIGH — tracks mutable branch
- First-party (
actions/*) with version tags = acceptable risk
- Third-party with only version tags = MEDIUM — recommend pinning to SHA
-
Permissions audit: For each workflow:
- Missing top-level
permissions: = MEDIUM (defaults to broad read/write)
permissions: write-all or contents: write where not needed = MEDIUM
- Check if each permission granted is actually used
id-token: write should only be present for OIDC deployments (e.g., GitHub Pages, cloud providers)
-
Secret exposure patterns:
- Secrets passed to steps that don't need them
- Secrets in
env: at workflow level instead of step level (broader exposure)
- Secrets logged via
echo or debug output
- SSH keys or tokens not cleaned up in
if: always() steps
-
Repository visibility context:
- Public repos: all checks above apply at full severity
- Private repos: Pwn Request and script injection are lower risk (no external contributors by default) but still flag as LOW — a compromised contributor account or future visibility change could expose them
Report sections: Workflow inventory table (name, triggers, permissions, secrets used), findings by severity, third-party action inventory, remediation steps.
Domain: pentest
- Confirm target URL with the user
- Run OWASP ZAP baseline scan:
~/.claude/bin/owasp-zap-scan.sh <url>
- Read the generated reports (JSON + markdown in
/tmp/zap-results/)
- Triage findings: Classify each as actionable vs. false positive vs. accepted risk
Report sections: ZAP scan summary, triaged findings, remediation priorities.
Phase 3: Generate Report
Produce a structured report with:
Report Format
## Security Audit Report: <domain>
**Issue:** #<number> (if applicable)
**Date:** <today>
**Auditor:** Claude Code (automated)
### Executive Summary
<1-3 sentences: overall assessment and critical findings count>
### Findings
| # | Severity | Finding | File | Remediation |
|---|----------|---------|------|-------------|
| 1 | CRITICAL | ... | path:line | ... |
| 2 | HIGH | ... | path:line | ... |
| 3 | MEDIUM | ... | path:line | ... |
### Detailed Findings
<per finding: description, evidence, remediation steps>
### Verified Controls
<what was checked and found to be secure — important for audit trail>
### Recommendation
<PASS / PASS WITH WARNINGS / FAIL — and next steps>
Phase 4: Post Report to Issue
If $ARGUMENTS was an issue number:
- Write the report to
/tmp/security-audit-report-$ARGUMENTS.md using the Write tool
- Post as issue comment:
gh issue comment $ARGUMENTS --body-file /tmp/security-audit-report-$ARGUMENTS.md
- If all findings are informational or verified-secure:
- Suggest closing the issue (don't close it — let the user decide)
- If actionable findings exist:
- Keep the issue open
- Suggest adding the findings as acceptance criteria checkboxes
If $ARGUMENTS was a domain keyword:
- Present the report directly to the user
- Suggest creating an issue if actionable findings exist