# Backend Security Audit

> Audit a backend against the OWASP API Security Top 10 — BOLA/BFLA, injection, secrets, mass assignment — with an exploit scenario per finding. Use when adding auth/external input, before shipping, or on a quarterly security review. Not for implementing auth from scratch (use authentication / authorization) — each finding maps to its sibling skill for the fix.

- Skill: `jaykim88/backend-security-audit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add jaykim88/backend-security-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jaykim88/backend-security-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- License: MIT
- Author: JayKim88 (https://skillmd.com/u/jaykim88)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/jaykim88/backend-security-audit

---


# Backend Security Audit

## Purpose
Systematically check a backend against the OWASP API Security Top 10, producing findings with a concrete exploit scenario each — so the team understands the *attack*, not just the rule.

**Universal** — the OWASP API Top 10 is a vendor-neutral, exploit-oriented taxonomy that maps to any backend; only the fix syntax differs.

## Procedure

Audit against the OWASP API Security Top 10 (2023). For each finding, **write the exploit scenario** (how an attacker abuses it) — this is the differentiator from a generic checklist.

1. **API1 BOLA (Broken Object Level Authorization)** — #1, ~40% of API attacks
   - Can a user access another's object by changing an ID? → row-level authz missing (see `authorization` RLS)
2. **API2 Broken Authentication**
   - Weak tokens, no rotation, alg confusion (see `authentication`)
3. **API3 Broken Object Property Level Authorization** (mass assignment / excessive data exposure)
   - Does the API accept/return fields the user shouldn't set/see? → explicit allow-lists, DTOs
4. **API5 BFLA (Broken Function Level Authorization)**
   - Can a regular user hit admin endpoints? → RBAC at every privileged route
5. **API4 Unrestricted Resource Consumption**
   - Rate limiting, pagination caps, payload size limits, query depth/complexity limits (GraphQL)
6. **API8 Security Misconfiguration**
   - CORS not wildcard for credentialed endpoints; security headers; verbose errors disabled in prod
7. **Injection (cross-cutting)**
   - Note: standalone "Injection" was API8:2019 — in the 2023 edition it's folded across categories rather than its own item, but still audit it
   - Parameterized queries only (ORM by default); never string-concatenate SQL; validate input (see `data-validation`)
8. **Secrets management (cross-cutting)**
   - Not a numbered Top-10 item but a practical must: no secrets in code/client-shipped env; use a secret manager; rotate; scan with `gitleaks`/`trufflehog`

9. **API7 SSRF (Server-Side Request Forgery)** — call this out explicitly
   - User-supplied URL fed into `fetch` / `axios` → attacker pivots through the server. Defenses: allowlist hosts; **block cloud metadata IPs** (`169.254.169.254` AWS/GCP/Azure, `100.100.100.200` Alibaba, link-local + private CIDRs); validate the resolved IP, not just the input string (DNS rebinding); set a strict timeout
   - Egress firewall is the structural defense; URL validation alone is not enough

10. **API10 Unsafe Consumption of APIs** — trust the wire as much as the user
   - Treat third-party API responses as untrusted: validate shape (see `data-validation`), cap response sizes, time out generously but not infinitely
   - JSON-bomb / zip-bomb / oversized-payload defenses on every downstream consumer

11. **CSRF (cookie-auth web apps)** — outside the *API* Top 10 but on the same backend
   - For sessions / cookie tokens: `SameSite=Lax|Strict` cookies + origin check on state-changing requests (header-token tokens like `Authorization` are immune)
   - Also review remaining 2023 items not enumerated above (API6 Sensitive Business Flows, API9 Improper Inventory)

12. **Validate (validation loop)**
   - For each Critical finding, reproduce the exploit (BOLA: actually fetch another user's record) → fix → re-attempt → verify blocked
   - Run `eslint-plugin-security` / `semgrep --config=auto` + `gitleaks` + dependency `audit`; triage each hit; re-run until clean or documented

## Anti-patterns

| ❌ Anti-pattern | ✅ Correct |
|---|---|
| Object access by ID with no ownership check | Row-level authz (RLS) verified per request |
| String-concatenated SQL | Parameterized queries / ORM |
| Accepting all body fields (mass assignment) | Explicit DTO allow-list |
| Secrets in env vars shipped to client | Secret manager; server-only; scanned |
| Wildcard CORS on credentialed endpoints | Explicit origin allow-list |
| User-supplied URL fed into `fetch` (SSRF) | Allowlist hosts; block metadata IPs (`169.254.169.254`); validate resolved IP, not just input |
| Trusting third-party API response shape (API10) | Validate shape + cap response size + bounded timeout |
| Cookie-auth state-changing endpoint with no CSRF defense | `SameSite=Lax/Strict` + origin / CSRF-token check |

## Severity tiers

| Tier | Examples | Action SLA |
|---|---|---|
| **Critical** | BOLA leaking other users' data; SQL injection; secret in repo; admin endpoint reachable by regular user (BFLA); SSRF reachable to cloud metadata; cookie-auth state-change with no CSRF defense | Block release; fix immediately |
| **Major** | Missing rate limits; mass assignment; CORS wildcard; trusting third-party API response without validation/size cap | Fix this sprint |
| **Minor** | Verbose error messages; missing security header; outbound URL allow-list maintained ad-hoc | Schedule within 2 sprints |

## Completion Criteria
- [ ] Key OWASP API Top 10 (2023) categories checked + cross-cutting concerns (injection, secrets)
- [ ] Each finding has an exploit scenario
- [ ] BOLA reproduced + fixed + re-verified blocked
- [ ] Static analysis + secret scan clean (or documented)
- [ ] All Critical fixed; all Major scheduled

## Output
- **Report**: `docs/security-audit-YYYY-MM-DD.md` — per finding: OWASP category, file:line, **exploit scenario**, fix, severity
- **Code fixes** per finding
- **Commit format**: `fix(security): <description> [OWASP-API#N, severity]`

## Stop & Ask (AI must pause for user approval)

- **Before changing auth/authz logic** to fix a finding — can lock users out if wrong
- **Before rotating/removing a secret** found in the repo — coordinate rotation with deploys
- **Before tightening CORS/CSP** in production config — verify no legitimate client breaks

## Implementation

### TypeScript + NestJS + Supabase (default)
- Injection: Prisma parameterizes by default; never `$queryRawUnsafe` with interpolation
- BOLA/BFLA: NestJS guards (RBAC) + Supabase RLS (row) — see `authorization`
- Mass assignment: explicit DTOs + `class-validator`/Zod (see `data-validation`)
- Scanning: `eslint-plugin-security`, `semgrep --config=auto`, `gitleaks`, `npm audit`

### Other stacks
- **Python / FastAPI**: `bandit` static analysis; Pydantic prevents mass assignment; parameterized SQLAlchemy
- **Go**: `gosec`; `database/sql` parameterized queries
- **Universal**: OWASP API Top 10 categories are framework-independent; `semgrep`, `gitleaks`, `trivy` work across stacks

## Related skills
- `authorization` — BOLA/BFLA findings are fixed via RBAC + RLS
- `authentication` — broken auth is a top OWASP category
- `data-validation` — input validation is the first injection defense

## Reference
- **Key insight encoded**: BOLA is the #1 API vulnerability — function-level auth without row-level auth is the most common gap. Every finding gets a reproducible exploit scenario.

