leistungsbilanz-ts/.claude/skills/security-review/references/asvs-light.md
Grovy311 67476ea59b Add agent security skills for Codex and Claude Code
Same skills in .agents/skills (Codex) and .claude/skills (Claude Code):
codeguard, security-review, dependency-vetting, pre-release-gate,
authz-idor-audit, threat-model-light. Source: cj/claude-skills.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:40:33 +02:00

68 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ASVS-light – Checkliste für eigene Apps
Angelehnt an OWASP ASVS, reduziert auf das, was bei kleinen selbst gebauten Apps (FastAPI,
Express, React/Next) regelmäßig schiefgeht. Jeder Punkt ist prüfbar. Spalte „Beleg“ sagt,
womit man ihn nachweist.
Prioritäten: **K** = Kritisch (No-Go, wenn offen), **H** = Hoch, **M** = Mittel.
## 1. Authentifizierung
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| A1 | K | Jede Route außer einer expliziten Public-Liste verlangt Login | Test „jede Route verlangt Auth“ (Routen aus OpenAPI/Router, Leerlauf-Sperre) |
| A2 | K | Identität kommt aus geprüfter Quelle (Session, JWT mit Signaturprüfung, Proxy-Header nur mit Shared Secret) | Spoofing-Test: gefälschter Header ohne Secret → 401 |
| A3 | K | App-Port ist nicht am Reverse-Proxy vorbei erreichbar (Compose: kein `ports:` oder nur `127.0.0.1:`) | `docker compose config`, `ss -tlnp`, Zugriff von anderem Host |
| A4 | H | Session-Cookies: `HttpOnly`, `Secure`, `SameSite=Lax/Strict` | Test auf `Set-Cookie` |
| A5 | H | Login/Token-Endpunkte haben Rate-Limit | Konfiguration + Test |
| A6 | M | Logout invalidiert die Session serverseitig | Test |
## 2. Autorisierung
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| B1 | K | Objektzugriff wird pro Objekt geprüft (kein IDOR): Nutzer B kann Objekt von A weder lesen noch ändern noch löschen | IDOR-Tests mit zwei Nutzern |
| B2 | K | Listen-Endpunkte liefern nur erlaubte Objekte | Test: Liste von B enthält nichts von A |
| B3 | H | Rollenmatrix ist dokumentiert und als Tests abgebildet | Skill `authz-idor-audit` |
| B4 | H | Rechte werden serverseitig geprüft, nicht nur im UI versteckt | Test direkt gegen API |
| B5 | M | Admin-Funktionen auf eigenen Routen mit eigener Prüfung | Code-Review |
## 3. Eingaben
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| C1 | K | SQL ausschließlich parametrisiert / ORM, keine String-Verkettung | Semgrep-Regeln, Ruff S608 |
| C2 | H | Alle Request-Bodies laufen durch Schemas mit „unbekannte Felder verboten“ (Pydantic `extra="forbid"`, zod `.strict()`) | Mass-Assignment-Test (`role`, `owner`, `leader` im Body → 422/400) |
| C3 | H | Ungültige Eingaben → 4xx, nie 500 | Test ungültige Eingabe, Fuzzing (`make fuzz`) |
| C4 | H | Kein `eval`/`exec`, kein `shell=True`, kein unsicheres Deserialisieren (`pickle`, `yaml.load`) | Semgrep, Bandit |
| C5 | M | Datei-Uploads: Typ/Größe begrenzt, Pfad nicht vom Client bestimmt | Test |
## 4. Frontend
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| D1 | H | Kein `dangerouslySetInnerHTML`/`innerHTML` mit nicht vertrauenswürdigen Daten | ESLint `react/no-danger`, Semgrep |
| D2 | H | Keine Tokens/Secrets in `localStorage`/`sessionStorage` | Semgrep, Playwright-Test auf Web Storage |
| D3 | M | Security-Header gesetzt (CSP, `X-Content-Type-Options`, `frame-ancestors`) | ZAP-Baseline (`make zap`) |
| D4 | M | Keine Secrets im Frontend-Bundle (`NEXT_PUBLIC_*`, `VITE_*` prüfen) | gitleaks auf Build-Output |
## 5. Konfiguration
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| E1 | K | Keine Secrets im Repo oder in der Git-Historie | gitleaks (Pre-Commit + CI) |
| E2 | K | CORS: kein `*`, kein `origin: true` zusammen mit Credentials | CORS-Test, Semgrep |
| E3 | H | Debug-Modus aus, API-Docs in Prod aus oder geschützt | Prod-Konfigurationstest |
| E4 | H | Fehlerantworten ohne Stacktrace/Exception-Text | Test auf generische 500er |
| E5 | H | TLS-Prüfung nie abgeschaltet (`verify=False`, `rejectUnauthorized:false`, `NODE_TLS_REJECT_UNAUTHORIZED=0`) | Semgrep |
| E6 | M | Container läuft nicht als root, Image ohne High/Critical | `make container` (Trivy, hadolint) |
## 6. Abhängigkeiten
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| F1 | K | Keine High/Critical-Lücken ohne dokumentierte Ausnahme | `make audit` |
| F2 | H | Jede neue Dependency vorher geprüft (existiert, nicht typosquat, gepflegt) | Skill `dependency-vetting`, `make vet-deps` |
| F3 | M | Lockfile im Repo (`package-lock.json`, `requirements*.txt` gepinnt) | Repo |
## 7. Datenschutz
| ID | Prio | Punkt | Beleg |
|----|------|-------|-------|
| G1 | H | Gesundheitsdaten (z. B. Abwesenheitsgrund „krank“) nur speichern, wenn nötig; sonst neutrale Abwesenheit | Datenmodell |
| G2 | H | Logs ohne personenbezogene Daten, Tokens, Passwörter | Code-Review, Log-Stichprobe |
| G3 | M | Testdaten synthetisch, keine echten Mitarbeiter-/Kundendaten in Tests, Fixtures, Seeds | Review |
| G4 | M | Löschkonzept: wer löscht wann welche Personendaten | Doku |