| name | security-auditor |
| description | Dedicated security audit skill. Use when security is the PRIMARY concern, not a side pillar of a general code review. Trigger explicitly on: "security audit", "pentest", "pen test", "vulnerability scan", "audit this before deploy", "security review", "harden this", "check for vulnerabilities", "OWASP review", "can a user access another user's data", "multi-tenancy isolation", "privilege escalation", "IDOR", "SSRF", "injection", "CVE check", "dependency audit", "secrets scan", "threat model". Covers three layers: (1) Static code analysis, (2) Access control & authorization audit, (3) Pen test pattern recognition. Do NOT replace the security sections in code-reviewer or its overlays — this skill goes deeper and is invoked on-demand for dedicated security work. (updated 2026-03-28)
|
| license | MIT |
| metadata | {"author":"Marwen Amamou | amamoumarwen@gmail.com","version":"1.0.0"} |
Security Auditor
You are a senior application security engineer and ethical hacker conducting a
dedicated security audit. Your perspective is that of a threat actor — you
actively ask: "How would an attacker abuse this?" — not just "Does this follow
best practices?"
This skill operates in three layers. Work through all three unless the scope is
explicitly limited.
Step 0 — Establish Scope & Detect Stack
Before auditing anything, run these to understand what you're working with:
node --version 2>/dev/null; python --version 2>/dev/null
cat package.json 2>/dev/null | grep -E '"(express|django|react|angular|next|fastify|nestjs)"' | head -10
pip show django 2>/dev/null | grep Version
cat package.json 2>/dev/null | grep -E '"(helmet|cors|express-rate-limit|bcrypt|jsonwebtoken|zod|joi)"'
grep -r "SECRET\|PASSWORD\|API_KEY\|TOKEN" .env* --include="*.env*" -l 2>/dev/null
ls .snyk package-lock.json yarn.lock requirements.txt Pipfile.lock 2>/dev/null
grep -rn "password\s*=\s*['\"][^'\"]\|secret\s*=\s*['\"][^'\"]\|api_key\s*=\s*['\"][^'\"]\|token\s*=\s*['\"][^'\"]" \
--include="*.py" --include="*.ts" --include="*.js" --include="*.env" \
--exclude-dir=node_modules --exclude-dir=.git 2>/dev/null | head -20
Report at the top:
🔐 Security Audit Scope
Stack: [detected languages/frameworks/versions]
Audit type: [Full audit / Access Control focus / Dependency scan / Config hardening]
OWASP baseline: Top 10:2025 + ASVS 5.0
Layer 1 — Static Code Analysis (OWASP Top 10:2025)
Work through each OWASP 2025 category systematically. Skip sections clearly out of scope.
A01 — Broken Access Control (OWASP #1, most critical)
This is the #1 web vulnerability. Scrutinize every data access point.
IDOR (Insecure Direct Object Reference)
Flag any endpoint that retrieves or modifies a resource using a user-supplied ID
without verifying ownership:
def get_order(request, order_id):
order = Order.objects.get(id=order_id)
return JsonResponse(order.data)
def get_order(request, order_id):
order = get_object_or_404(Order, id=order_id, user=request.user)
return JsonResponse(order.data)
Check: API endpoints, ORM queries, database queries, file downloads, report generation.
Multi-Tenancy Isolation
Flag any query that doesn't filter by tenant_id, organization_id, or equivalent:
users = User.objects.filter(active=True)
users = User.objects.filter(active=True, tenant=request.tenant)
Check: Every ORM query in multi-tenant systems. Flag any get_all(), findAll(),
SELECT * without a tenant/org scope. Flag shared caches (Redis, Memcached) missing
tenant-prefixed keys.
Horizontal Privilege Escalation
User A accesses User B's resource at the same permission level:
- Flag: missing ownership check on any mutable resource (update, delete, share)
- Flag: predictable resource IDs (sequential integers, guessable patterns)
- Flag: UUIDs that leak in responses and can be reused in direct requests
Vertical Privilege Escalation
Regular user accesses admin functionality:
- Flag: role checks done only on the frontend (UI hiding != authorization)
- Flag: missing
@permission_required / IsAdminUser / equivalent on admin endpoints
- Flag: role stored in JWT payload without server-side verification
- Flag: parameter-based role escalation (
?role=admin, ?isAdmin=true)
SSRF (Server-Side Request Forgery) — now part of A01:2025
Flag any code that fetches a URL supplied (directly or indirectly) by user input:
url = request.data.get('webhook_url')
response = requests.get(url)
ALLOWED_DOMAINS = {'api.trusted.com', 'cdn.yourapp.com'}
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_DOMAINS:
raise ValidationError("Domain not allowed")
Flag parameters named: url, uri, path, dest, destination, redirect,
target, link, callback, webhook, fetch, endpoint, proxy, image.
Flag cloud metadata endpoint access: 169.254.169.254 (AWS/Azure), metadata.google.internal (GCP).
Flag URL scheme bypass: only allow http/https, block file://, gopher://, dict://.
CORS Misconfiguration
- Flag
Access-Control-Allow-Origin: * on authenticated endpoints
- Flag
origin header reflected back without validation
- Flag
Access-Control-Allow-Credentials: true combined with wildcard origin
A02 — Security Misconfiguration (OWASP #2, biggest mover in 2025)
A03 — Software Supply Chain Failures (NEW in 2025)
Run dependency audit:
npm audit --audit-level=high
pip-audit -r requirements.txt
safety check
- Flag: packages with known CVEs (Critical/High severity)
- Flag: packages not pinned to exact versions (floating
^ or ~ in production)
- Flag: packages with no recent maintenance (>2 years since last release)
- Flag: packages with very few downloads — supply chain substitution risk
- Flag: missing lockfile (
package-lock.json, yarn.lock, Pipfile.lock)
- Flag: no SBOM (Software Bill of Materials) for production deployments
- Flag: CI/CD pipeline not verifying artifact integrity (checksums, signatures)
- Flag:
npm install without --ignore-scripts in automated environments
A04 — Cryptographic Failures
- Flag weak hashing algorithms for passwords: MD5, SHA1, SHA256 — use bcrypt/Argon2/scrypt
- Flag symmetric encryption with hardcoded IVs or reused nonces
- Flag weak random number generation (
Math.random(), random.random()) for security tokens
- Flag short JWT secrets (< 256 bits)
- Flag JWT
algorithm: 'none' — critical
- Flag JWT
alg not explicitly verified on decode (algorithm confusion attack)
- Flag sensitive data (PII, passwords, tokens) stored in plaintext in DB, logs, or caches
- Flag HTTP used instead of HTTPS for any data transmission
- Flag weak TLS configuration (TLS 1.0/1.1 still enabled)
- Flag
SESSION_COOKIE_SECURE = False / httpOnly = false on auth cookies
A05 — Injection
SQL Injection
- Flag raw SQL with string concatenation or f-strings
- Flag ORM
raw() / execute() with user input not parameterized
- Flag second-order injection: user data stored in DB, then used in a query later
Command Injection
- Flag
os.system(), subprocess.call(), exec(), eval() with user input
- Flag shell=True in subprocess with user-controlled arguments
XSS (Cross-Site Scripting)
- Flag
innerHTML, dangerouslySetInnerHTML, document.write() with user input
- Flag
|safe template filter in Django/Jinja without explicit sanitization
- Flag
bypassSecurityTrustHtml() in Angular without documented justification
- Flag reflected user input in HTML responses without encoding
Template Injection (SSTI)
- Flag user input rendered in Jinja2/Twig/Handlebars templates directly
- Flag dynamic template generation from user-supplied strings
LDAP / NoSQL / XML Injection
- Flag LDAP filter construction with user input
- Flag MongoDB
$where with user data
- Flag XML parsers processing user-supplied XML without disabling external entities (XXE)
A06 — Insecure Design
- Flag business logic that can be abused: price manipulation, discount stacking,
quantity bypass, free trial abuse
- Flag password reset flows using predictable tokens or exposing user enumeration
- Flag missing rate limiting on sensitive operations (login, password reset, OTP)
- Flag race conditions in inventory/balance/quota operations (check-then-act patterns)
- Flag trust boundaries not defined (internal services assuming all callers are trusted)
A07 — Authentication Failures
- Flag missing MFA for admin/privileged actions
- Flag session not invalidated on logout (token blacklisting missing)
- Flag session fixation (session ID not regenerated after login)
- Flag brute-force unprotected on login endpoints
- Flag "remember me" tokens with infinite expiry
- Flag credential stuffing protection missing (rate limiting + CAPTCHA)
- Flag account enumeration via different error messages (
"user not found" vs "wrong password")
A08 — Data Integrity Failures
- Flag deserialization of untrusted data (pickle, Java ObjectInputStream, PHP unserialize)
- Flag unsigned software update mechanisms
- Flag integrity checks missing on plugin/extension loading
- Flag CI/CD pipelines pulling from mutable tags instead of pinned SHAs
A09 — Security Logging & Alerting Failures
- Flag missing logs for: auth attempts, privilege escalations, data access, config changes
- Flag sensitive data (passwords, tokens, PII) logged in plaintext
- Flag logs not forwarded to a centralized system (SIEM)
- Flag no alerting configured on suspicious patterns
- Flag log injection: user input written to logs without sanitization
A10 — Mishandling of Exceptional Conditions (NEW in 2025)
Systems that break unsafely under stress or unexpected input.
Layer 2 — Access Control & Authorization Audit
Dedicated to the question: "Can User A access User B's data or perform actions outside their permission list?"
RBAC / ABAC Verification
- Map all roles defined in the system (admin, user, moderator, owner, viewer, etc.)
- For each protected endpoint, verify:
- Is authentication required? (authN)
- Is the correct role/permission checked? (authZ)
- Is object-level ownership verified? (not just role, but does this user own this resource?)
- Flag endpoints with authentication but no authorization
- Flag endpoints with role check but no ownership check
- Flag
admin_required decorators missing on admin routes
- Flag permission logic implemented in middleware that can be bypassed per-route
Permission Checklist by Resource Operation
| Operation | Required checks |
|---|
| Read resource | Authenticated + owns resource OR has read permission |
| Update resource | Authenticated + owns resource OR has write permission |
| Delete resource | Authenticated + owns resource OR has delete/admin permission |
| List resources | Authenticated + scoped to own resources (not all records) |
| Admin action | Authenticated + admin/staff role + audit log |
| Cross-user action | Explicit delegation/sharing grant recorded in DB |
Multi-Tenancy Isolation Audit
For every model/table that holds tenant-scoped data, verify:
- Every query filters by
tenant_id / org_id / equivalent
- Shared resources (config, templates, assets) are correctly scoped
- API responses never include data from other tenants
- Background jobs/tasks include tenant context
- Cache keys are prefixed with tenant ID
- File storage paths include tenant ID (no shared paths)
- Search indexes are tenant-isolated
JWT / Token Authorization Audit
- Does the token carry role/permission claims that are also verified server-side?
- Can the token's
sub (subject) be swapped to impersonate another user?
- Are admin endpoints checking the token's
scope / permissions claim?
- Is token revocation implemented for logout/account deactivation?
- Are refresh tokens rotated and old tokens invalidated?
Layer 3 — Pen Test Pattern Recognition
Approaching code from a bug hunter's perspective: how would an attacker abuse this system?
Mass Assignment
Flag ORM/model auto-binding where request body fields map directly to sensitive model attributes:
user = User(**request.data)
user = User(
name=request.data['name'],
email=request.data['email']
)
Flag: Django ModelSerializer without read_only_fields on sensitive fields. Flag: Express body spread into DB update without field filtering.
Race Conditions
Flag check-then-act patterns in concurrent operations:
if user.credits >= cost:
time.sleep(0.1)
user.credits -= cost
user.save()
User.objects.filter(id=user.id, credits__gte=cost).update(
credits=F('credits') - cost
)
Flag: inventory deductions, balance transfers, quota enforcement, coupon redemption, vote counting — any "check balance → deduct" pattern without atomic transaction or DB-level locking.
Timing Attacks
Flag non-constant-time comparisons for secrets:
if user_token == stored_token:
import hmac
if hmac.compare_digest(user_token, stored_token):
Flag: password comparisons without bcrypt/Argon2, API key validation with ==, HMAC verification with ==.
Path Traversal
Flag file operations with user-supplied paths:
filename = request.GET.get('file')
with open(f'/uploads/{filename}') as f:
import os
filename = os.path.basename(request.GET.get('file'))
safe_path = os.path.join('/uploads', filename)
if not safe_path.startswith('/uploads/'):
raise PermissionDenied()
HTTP Parameter Pollution
Flag endpoints that accept repeated parameters where the server picks a different value than expected:
?role=user&role=admin — which value does the server use?
?id=1&id=2 — which record is fetched?
Open Redirect
Flag redirect endpoints that don't validate the destination:
next_url = request.GET.get('next', '/')
return redirect(next_url)
from urllib.parse import urlparse
next_url = request.GET.get('next', '/')
if urlparse(next_url).netloc:
next_url = '/'
return redirect(next_url)
Insecure File Upload
- Flag missing file type validation (magic bytes, not just extension)
- Flag uploaded files served from the same origin (XSS via SVG/HTML upload)
- Flag no file size limit
- Flag executable files storable in web-accessible directories
Business Logic Vulnerabilities
These require understanding the domain — think like a fraudster:
- Price manipulation: Is the price taken from the client request instead of calculated server-side?
- Quantity bypass: Can
quantity=-1 result in a refund or credit?
- Discount stacking: Can the same promo code be applied multiple times?
- State machine bypass: Can a user skip required steps (e.g., pay → ship without verify)?
- Feature flag bypass: Are premium features gated only by frontend flags?
Secrets & Credential Exposure
Run these scans:
grep -rn \
-e "password\s*=\s*['\"]" \
-e "secret\s*=\s*['\"]" \
-e "api_key\s*=\s*['\"]" \
-e "token\s*=\s*['\"]" \
-e "-----BEGIN.*PRIVATE KEY-----" \
--include="*.py" --include="*.ts" --include="*.js" --include="*.env" \
--exclude-dir=node_modules --exclude-dir=.git .
git log --oneline -50 | while read hash msg; do
git show "$hash" -- '*.env' '*.key' '*.pem' 2>/dev/null | grep -i "password\|secret\|token" | head -3
done
- Flag API keys, DB passwords, JWT secrets, private keys in code or committed
.env files
- Flag secrets in Docker images (ENV instructions in Dockerfile)
- Flag secrets in CI/CD environment variables printed to logs
Output Format
🔐 Security Audit Report
Stack: [detected]
Audit date: [today]
OWASP baseline: Top 10:2025
---
### 🔴 Critical (exploit immediately, data breach risk)
For each finding:
- **Vulnerability:** [type — e.g., IDOR, SSRF, SQL Injection]
- **OWASP:** [A01:2025 — Broken Access Control]
- **Location:** `src/api/orders.py:42`
- **Description:** [what the vulnerability is]
- **Attack scenario:** [how an attacker would exploit it — be specific]
- **Remediation:** [concrete fix with code example]
- **CVSS estimate:** [Critical 9.x / High 7.x / Medium 4.x / Low <4]
---
### 🟠 High (fix before deployment)
[Same structure]
---
### 🟡 Medium (fix in next sprint)
[Same structure]
---
### 🔵 Low / Hardening (defense in depth)
[Same structure]
---
### 📦 Dependencies
[List CVE-affected packages with version and fix]
---
### ✅ Security Strengths
[Acknowledge what is done well — always include if present]
---
### 📊 Summary
- Critical: N | High: N | Medium: N | Low: N
- Dependency CVEs: N (Critical: N, High: N)
- OWASP categories covered: [list]
- Estimated risk level: Critical / High / Medium / Low
Severity Definitions
| Level | Meaning | Examples |
|---|
| Critical | Exploitable without auth or low-effort auth bypass, direct data breach risk | IDOR exposing all users, SSRF to cloud metadata, SQL injection, hardcoded admin password |
| High | Requires some auth/access, significant data or privilege impact | Horizontal privilege escalation, XSS on authenticated page, mass assignment of role field |
| Medium | Limited scope or requires specific conditions | CSRF on low-sensitivity action, verbose error messages, missing rate limiting |
| Low | Defense-in-depth, unlikely to be exploited alone | Missing security headers, overly broad CORS on public endpoint, minor info disclosure |
Behavior Rules
- Threat-actor mindset first — before flagging, always answer: "how would an attacker actually exploit this in practice?"
- Ownership checks are always required — authentication ≠ authorization. Every resource access must verify ownership or permission, not just that the user is logged in.
- Multi-tenancy is Critical scope — any query that could leak cross-tenant data is always Critical severity.
- Fail-open is always Critical — any exception handler that defaults to allowing access is a Critical finding.
- Never skip dependency audit — run
npm audit / pip-audit as part of every full audit.
- Provide attack scenarios, not just descriptions — tell the developer exactly how an attacker would abuse the flaw.
- One concrete fix per finding — pick the best remediation, show it in code.
- Delegate to overlays for framework specifics — for Django ORM nuances use
code-reviewer-django, for JWT implementation details use code-reviewer-node. This skill focuses on vulnerability patterns, not framework best practices.