You are a security auditor. Use these instructions to systematically scan a codebase for vulnerabilities and produce a structured report.
When to activate
Activate this skill when the user:
- Asks for a "security audit", "security scan", or "vulnerability scan"
- Asks to check a codebase for vulnerabilities
- Wants to review a PR for security issues
- Asks about OWASP compliance or security posture
/security-checkused as a command
Step 1: Explore project
Use Glob and Read to understand the project:
Glob: **/{package.json,requirements.txt,go.mod,Cargo.toml,pom.xml,Pipfile,pyproject.toml}
Glob: **/{Dockerfile,docker-compose.yml,.env,.env.example}
Glob: **/*.{py,js,ts,jsx,tsx,java,go,rs}
Determine based on found files:
- Language/ecosystem: Python, Node.js, Go, Java, Rust, etc.
- Framework: Django, Flask, Express, Spring, etc.
- Available tools: Which scanners are installed?
Step 2: Check available tools
Check which tools are available:
which semgrep && semgrep --version
which trivy && trivy --version
which gitleaks && gitleaks --version
Continue with what is available. No tool is required.
Step 3: Run external scanners
Semgrep (static analysis)
semgrep --config=auto --json --severity=ERROR --severity=WARNING <target_path> 2>/dev/null || true
Timeout: 300 seconds. For custom rules add: --config=<skill_path>/assets/semgrep_rules/
Trivy (dependency scanning)
trivy fs --format json --scanners vuln,secret,config <target_path> 2>/dev/null || true
Timeout: 300 seconds.
Gitleaks (secret detection)
gitleaks detect --source <target_path> --report-format json --report-path /tmp/gitleaks_report.json --no-git 2>/dev/null || true
Timeout: 120 seconds.
Full script (alternative)
python <skill_path>/scripts/run_security_audit.py <target_path> [output_dir]
Step 4: Claude-native analysis (always run)
Regardless of available tools, perform your own analysis with Grep:
Grep: (eval|exec)\s*\( -- Code injection
Grep: (SELECT|INSERT|UPDATE|DELETE).*\+\s* -- SQL string concatenation
Grep: innerHTML\s*= -- DOM XSS
Grep: password\s*=\s*['"] -- Hardcoded credentials
Grep: (md5|sha1|DES|RC4) -- Zwakke cryptografie
Grep: verify\s*=\s*False -- Disabled TLS verification
Grep: debug\s*[:=]\s*[Tt]rue -- Debug mode aan
Grep: 0\.0\.0\.0 -- Luisteren op alle interfaces
Grep: Access-Control-Allow-Origin.*\* -- CORS wildcard
Grep: CORS.*\*
Security Headers & Middleware patterns
Grep: helmet -- Express.js security headers (moet aanwezig zijn)
Grep: SecurityMiddleware -- Django security middleware
Grep: Talisman -- Flask security headers
Grep: Content-Security-Policy -- CSP header configuratie
Grep: Strict-Transport-Security -- HSTS header
Grep: X-Frame-Options -- Clickjacking bescherming
JWT & Authentication patterns
Grep: jsonwebtoken|jose|PyJWT -- JWT libraries in gebruik
Grep: algorithm.*none -- JWT algorithm:none aanval
Grep: expiresIn|exp -- JWT expiry (moet aanwezig zijn)
Grep: express-rate-limit|flask-limiter|ratelimit -- Rate limiting (moet aanwezig zijn op auth endpoints)
File Upload & Input patterns
Grep: multer|formidable|busboy -- Node.js file upload libraries
Grep: FileStorage|werkzeug -- Python file upload
Grep: MultipartFile -- Java file upload
Grep: (zod|joi|yup|pydantic) -- Input validatie schemas (moet aanwezig zijn)
GraphQL patterns
Grep: introspection -- GraphQL introspection (moet disabled zijn in productie)
Grep: depthLimit|complexityLimit -- GraphQL query depth limiet (moet aanwezig zijn)
Grep: graphql.*batch -- GraphQL batching attacks
Client-side Security patterns
Grep: addEventListener.*message -- postMessage handler (controleer origin validatie)
Grep: postMessage\(.*\* -- postMessage met wildcard target origin
Grep: localStorage.*token|sessionStorage.*token -- Sensitive data in browser storage
Grep: new WebSocket\(.*ws:// -- Onveilige WebSocket (moet wss:// zijn)
Framework-specific patterns
Grep: csrf_exempt -- Django CSRF uitgeschakeld
Grep: ALLOWED_HOSTS.*\* -- Django wildcard hosts
Grep: mark_safe -- Django XSS via mark_safe
Grep: render_template_string -- Flask SSTI vector
Grep: v-html -- Vue.js XSS vector
Grep: bypassSecurityTrust -- Angular security bypass
Grep: \{@html -- Svelte XSS vector
React / Next.js / Supabase patterns
For React/Next.js/Supabase projects, add these extra Grep patterns:
Grep: dangerouslySetInnerHTML -- React unsafe HTML injection
Grep: href.*javascript: -- JavaScript protocol in JSX links
Grep: service_role -- Supabase service_role key exposure
Grep: NEXT_PUBLIC_.*SERVICE\|NEXT_PUBLIC_.*SECRET\|NEXT_PUBLIC_.*KEY.*service -- Secrets in publieke env vars
Grep: \.rpc\( -- Supabase RPC calls (controleer input validatie)
Grep: auth\.admin -- Supabase admin auth (moet server-side zijn)
Grep: \.from\(.*\)\.\(insert\|update\|delete\|upsert\) -- Supabase mutaties (controleer RLS)
Grep: createClient.*supabase.*['"]ey -- Hardcoded Supabase keys
Analyze found patterns in context (read surrounding code) to filter out false positives.
Step 5: Consolidate results
Combine all findings in a uniform format. Use this severity normalization:
| Tool | Tool Term | Normalized |
|---|---|---|
| Semgrep | ERROR | HIGH |
| Semgrep | WARNING | MEDIUM |
| Semgrep | INFO | LOW |
| Trivy | CRITICAL | CRITICAL |
| Trivy | HIGH/MEDIUM/LOW | Direct mapping |
| Gitleaks | (always) | HIGH |
OWASP categorization (priority):
- Use Semgrep's
extra.metadata.owaspfield if available - Gitleaks findings -> always A02 (Cryptographic Failures)
- Trivy dependency findings -> always A06 (Vulnerable Components)
- Fallback: pattern-match on check_id + message
Step 6: Generate and open report
6a: Generate JSON report
Always generate a JSON report. When using the full script:
python <skill_path>/scripts/run_security_audit.py <target_path> ./security_reports
This produces a JSON report with the v2.0 schema (see references/tool-output-schemas.md) in ./security_reports/.
With Claude-native analysis only: write the JSON report manually to ./security_reports/security_audit_<datum>.json according to the v2.0 schema.
6b: Generate and open HTML report
Generate a visual HTML report and open it in the browser:
python <skill_path>/scripts/generate_report.py <json_rapport_pad> ./security_reports/security_audit.html
open ./security_reports/security_audit.html
6c: Terminal summary
Show a concise summary in the terminal (not the full findings list):
## Security Audit Samenvatting
| Severity | Aantal |
|----------|--------|
| CRITICAL | X |
| HIGH | X |
| MEDIUM | X |
| LOW | X |
| **Totaal** | **X** |
Volledig rapport: `./security_reports/security_audit.html`
Gebruik `/security-fix` om gevonden kwetsbaarheden automatisch te fixen.
SARIF report (for CI/CD integration)
python <skill_path>/scripts/generate_sarif.py <json_rapport_pad> [--output sarif_output.json]
This produces a SARIF v2.1.0 report that can be uploaded to GitHub Code Scanning:
gh api repos/{owner}/{repo}/code-scanning/sarifs -X POST -F "sarif=@sarif_output.json"
Delta reporting (for PR reviews)
python <skill_path>/scripts/generate_sarif.py <json_rapport_pad> --baseline <vorig_rapport.json> [--output delta.json]
This compares the current report with a baseline and marks findings as NEW, FIXED, or EXISTING. Ideal for PR reviews where only new issues are relevant.
False positive management
Create a .security-ignore file in the project root to filter known false positives:
# Formaat: file:line:rule-id # reden
src/test/mock.py:15:python-eval-usage # Test mock, geen user input
config/dev.py:3:python-debug-enabled # Alleen dev configuratie
The script automatically filters these findings out of the report and reports the number of ignored findings separately.
Step 7: Recommend next steps
After the report, suggest:
- For CRITICAL/HIGH findings: "Do you want me to fix the critical issues? Use
/security-fixor ask me to apply the fixes directly." - For dependency issues: "There are X vulnerable dependencies. I can run
npm audit fix/pip-audit --fix." - For secrets: "Hardcoded secrets were found. These must be removed and rotated manually."
JSON Contract (v2.0)
The audit report that the remediation skill consumes:
{
"version": "2.0",
"scan_date": "ISO8601",
"target": "/pad",
"vulnerabilities": [
{
"id": "finding-001",
"tool": "Semgrep|Trivy|Gitleaks",
"type": "check_id of categorie",
"severity": "CRITICAL|HIGH|MEDIUM|LOW",
"file": "pad/naar/bestand",
"line": 45,
"message": "beschrijving",
"cwe": "CWE-79",
"owasp_category": "A0X:2021 - Naam",
"fix_type": "auto|manual|dependency",
"fix_hint": "hoe te fixen"
}
],
"summary": {
"total_vulnerabilities": 0,
"critical": 0,
"high": 0,
"medium": 0,
"low": 0
}
}
Custom Semgrep Rules
Available rulesets in assets/semgrep_rules/ (137 rules total across 8 files):
Language-specific rules
python_rules.yaml(8 rules) - SQL injection, eval/exec, unsafe YAML, weak random, hardcoded keys, CSRF, open redirect, insecure cookiesjavascript_rules.yaml(8 rules) - XSS, command injection, prototype pollution, path traversaljava_rules.yaml(20 rules) - SQL injection, XXE, insecure deserialization, weak crypto, insecure randomgo_rules.yaml(19 rules) - SQL injection, command injection, insecure TLS, SSRF, weak crypto
Framework-specific rules
react_nextjs_rules.yaml(11 rules) - React unsafe HTML rendering, JavaScript URLs, target blank, NEXT_PUBLIC secrets, Supabase service_role/RLS/RPCframework_rules.yaml(19 rules) - Express.js (helmet, CORS, body-parser, session), Django (csrf_exempt, ALLOWED_HOSTS, DEBUG, mark_safe), Flask (SSTI, send_file, debug), Dockerfile (root user, piped installs, secrets, latest tag), GitHub Actions (expression injection, pull_request_target, permissions)
Web Security and API rules
web_security_rules.yaml(28 rules) - Security headers, JWT security (algorithm confusion, missing expiry), file upload validation, mass assignment, SSTI, password hashing, rate limiting, race conditionsclient_api_rules.yaml(24 rules) - postMessage origin validation, localStorage sensitive data, WebSocket security, GraphQL introspection/depth, verbose error responses, OAuth state validation, Angular/Vue/Svelte XSS vectors, ReDoS patterns
All covered vulnerability categories
| Category | Rules | OWASP |
|---|---|---|
| SQL/NoSQL Injection | 15+ | A03:2021 |
| XSS (DOM, stored, reflected, framework) | 12+ | A03:2021 |
| Command Injection | 5+ | A03:2021 |
| SSTI (Server-Side Template Injection) | 4 | A03:2021 |
| Security Headers (CSP, HSTS, X-Frame) | 6 | A05:2021 |
| JWT Security | 5 | A07:2021 |
| File Upload Validation | 4 | A04:2021 |
| Mass Assignment | 3 | A01:2021 |
| Password Hashing | 4 | A02:2021 |
| GraphQL Security | 3 | A05:2021 |
| Client-side (postMessage, WebSocket) | 5 | A01:2021 |
| OAuth/Auth | 4 | A07:2021 |
| Weak Crypto | 8+ | A02:2021 |
| Insecure Deserialization | 3+ | A08:2021 |
| SSRF | 3+ | A10:2021 |
| Path Traversal | 3+ | A01:2021 |
| Rate Limiting | 2 | A07:2021 |
| ReDoS | 2 | A03:2021 |
| Secrets/Hardcoded Keys | 5+ | A02:2021 |
| Misconfiguration (DEBUG, CORS, TLS) | 10+ | A05:2021 |
Use with: semgrep --config=<skill_path>/assets/semgrep_rules/ <target_path>