Secure App Scaffolder
Erzeugt eine von Grund auf sichere Anwendung, die den Standards ANSSI, CIS, FBI und OWASP ASVS Level 2 entspricht: TypeScript-Frontend, Python-Backend, gehärtetes PostgreSQL.
Layout, README und UI folgen dem Skill project-blueprint. Sicherheitsregeln dieses Skills haben Vorrang vor Bequemlichkeits- oder UX-Regeln.
Referenzdateien (beim Erstellen des passenden Artefakts lesen)
- reference/docker-compose.yml: gehärtetes Compose mit Secret-Bootstrap.
- reference/nginx.conf: Reverse Proxy mit TLS 1.3, hybridem PQ, Headern, Rate-Limits.
- reference/security-tests.md: verbindliche Sicherheitstestmatrix.
Wann verwenden
- Starten, Gerüstbau oder Architektur einer neuen Webanwendung oder eines Dienstes.
- Anfragen, die ANSSI, CIS, FBI, OWASP, Härtung, rootless, Compliance erwähnen.
- Hinzufügen von Authentifizierung, Autorisierung, Dateiuploads, Audit-Logs, Admin-Funktionen, Bereitstellungsdateien oder MCP-Endpunkten.
Bereitstellungsziele: Nur Docker und rootless Podman. Keine Kubernetes-, Helm- oder andere Orchestrator-Manifeste generieren, es sei denn, der Benutzer fordert dies explizit an.
0. Bedrohungsmodell
- Erstellen Sie
docs/security/threat-model.md(≤ 1 Seite): Vermögenswerte, Vertrauensgrenzen, Akteure, Hauptrisiken (STRIDE) und die jeweilige Kontrollmaßnahme. Aktualisieren Sie es, wenn eine neue Vertrauensgrenze auftritt (Upload, Webhook, LLM, MCP).
1. Container & Laufzeit
- Rootless: Jedes Image endet mit einem numerischen
USER(z. B.USER 10001:10001), einschließlich des Webservers (nginxinc/nginx-unprivileged, Port > 1024). - Minimale, fixierte Images: Multi-Stage-Builds; die Laufzeitstufe ist distroless oder slim ohne Shell, Compiler oder Paketmanager; Entwicklungsabhängigkeiten ausgeschlossen. Basis-Images per Digest fixiert. Neuestes stabiles Python.
- Härtung:
read_only,tmpfsfür beschreibbare Pfade,cap_drop: [ALL],no-new-privileges, standardmäßiges seccomp-Profil zur Laufzeit (niemalsunconfined),pids_limit, Speicherlimits, Healthchecks, Core-Dumps deaktiviert (ulimits: core: 0). Nur der Reverse Proxy veröffentlicht Ports; das Datenbanknetzwerk istinternal: true. Niemals den Docker/Podman-Socket mounten. - Keine Unterprozesse: kein
subprocess,os.system,shell=True. Erzwungen durch: keine Shell im Image, eine SAST-Regel und einen In-Prozess-seccomp-Filter, derexecve/execveatablehnt und nach dem Start in jedem Worker geladen wird (eine Ablehnung auf Containerebene würde verhindern, dass der Entrypoint selbst startet). - Garantie für den ersten Start: Bei einem sauberen Clone funktioniert
docker compose up(auchdocker-compose upundpodman compose up) beim ersten Versuch: keine.env, kein manueller Schritt, keine andere Voraussetzung als die Container-Engine. Images werden automatisch gebaut (build:). Es werden nur Compose Specification-Funktionen verwendet, die von Docker Compose v2 und podman-compose unterstützt werden. Keine Host-Pfade außerhalb des Repositorys. Veröffentlichte Ports > 1024. Keine CPU-Limits (in vielen rootless cgroup-Setups nicht verfügbar).make upist ein dünner Wrapper um denselben Befehl. - Keine hartcodierten Geheimnisse: Ein One-Shot-
init-Dienst generiert Geheimnisse in einem benannten Volume (0600), die über*_FILE-Variablen konsumiert werden. Geheimnisse werden in der Produktion aus Dateien gelesen, nicht aus Umgebungsvariablen. - Air-gapped: Alle JS/CSS/Schriftarten/Icons sind gebündelt; kein CDN, kein Runtime-Download, keine Telemetrie. Abhängigkeiten stammen beim Offline-Bauen aus einem internen Mirror (Nexus, Artifactory, devpi, Verdaccio).
- Vault-ready: Eine einzige Abstraktion für den Secrets-Provider (
fileStandard,vault/sopsin Produktion). - Internes TLS: Backend ↔ Datenbank über TLS; optionales mTLS zwischen Diensten.
2. Lieferkette & Scanning
- Fixierte Abhängigkeiten: Lockfiles committen;
npm ci,uv sync --frozenoderpip install --require-hashes..npmrcmitignore-scripts=true, es sei denn, ein Paket benötigt Installationsskripte (Allowlist). - Pre-Build-Gate:
npm audit --audit-level=highundpip-auditlassen den Build bei Exit-Code > 0 fehlschlagen. - SAST & Secrets: Pre-Commit mit
ruff,bandit/semgrep,eslint(+eslint-plugin-security),gitleaks. - Image-Scans (
make scan):trivy image(CVEs + Secrets + Fehlkonfigurationen),trivy configauf Dockerfiles und Compose,oscap-podman(oderoscap-docker) gegen das CIS-Profil des Basis-Betriebssystems. - SBOM & Signieren (
make sbom): CycloneDX-SBOM (Trivy oder Syft), Images mitcosignsigniert (schlüsselbasiert für Offline), SBOM als Attestation angehängt; die Bereitstellung überprüft die Signatur. - DAST (optional, empfohlen): OWASP ZAP Baseline gegen den laufenden Stack in CI.
- Updates: Renovate/Dependabot (oder eine gleichwertige Offline-Überprüfung) in einem festen Rhythmus.
3. Frontend (TypeScript)
- Speicherort:
/frontendmit eigenemDockerfile, als statische Assets gebaut, die von unprivilegiertem Nginx ausgeliefert werden. - CSP-kompatibler Code: kein Inline-
<script>, keineval/new Function, kein Runtime-CSS-in-JS, das<style>ohne Nonce injiziert. Kompiliertes CSS bevorzugen. Trusted Types aktiviert (require-trusted-types-for 'script'). - Zero-Trust-Eingabe: Getipptes Zod-Schema pro Formular, mit den API-Typen geteilt. Niemals
dangerouslySetInnerHTML/v-htmlauf nicht vertrauenswürdigen Daten; DOMPurify, wenn Rich-Text unvermeidbar ist. - Idempotenz: Der API-Client hängt einen
Idempotency-Key(UUIDv4) an jeden POST/PUT/PATCH/DELETE an, einmal pro Benutzeraktion generiert und bei Wiederholungen wiederverwendet. - CSRF: Benutzerdefinierter Header (
X-Requested-With) + CSRF-Token; Backend prüft auchOrigin/Sec-Fetch-Site. CORS-Allowlist nur, niemals*mit Credentials. - Offene Weiterleitungen: Post-Login
next/returnUrlakzeptiert nur relative Pfade, die mit einem einzelnen/beginnen. - Keine Geheimnisse im Bundle; keine Source Maps in der Produktion; keine sensiblen Daten in
localStorage/sessionStorage.
4. Backend (Python) & Datenbank
- Validierung: Jeder Body, Query-Parameter, Pfadparameter und Header wird von Pydantic mit maximalen Längen und
extra="forbid"validiert (verhindert Massenzuweisung:role,owner_id,is_adminsind nie aus der Eingabe bindbar). - Ressourcenlimits: Maximale Request-Body-Größe, maximale JSON-Tiefe/Array-Länge, maximale Seitengröße (z. B. 100), serverseitige Timeouts. Regexes auf Benutzereingaben sind begrenzt oder verwenden eine lineare Engine (
re2), um ReDoS zu vermeiden. - Sicheres Parsen: kein
pickle,marshal,yaml.load(verwenden Sieyaml.safe_load),eval. XML viadefusedxml. Keine Benutzereingabe in Vorlagenquellen (SSTI). Dateipfade werden aufgelöst und gegen ein Basisverzeichnis geprüft (Path Traversal). - Idempotenzspeicher:
(user_id, key) -> request_hash, status, response, 24 h TTL. Gleicher Schlüssel + gleicher Hash gibt die gespeicherte Antwort zurück; anderer Hash gibt422zurück. Dies verhindert Duplikate; Replay-Schutz kommt von TLS, CSRF-Tokens und kurzen Sitzungen. - SQL: ORM oder parametrisierte Abfragen nur; dynamische Bezeichner (
ORDER BY, Spaltennamen) über eine Allowlist. - Spaltenweise Verschlüsselung: PII wird in der App mit AES-256-GCM verschlüsselt, Envelope Encryption (pro-Datensatz DEK, die durch einen Masterschlüssel vom Secrets-Provider geschützt wird),
key_version-Spalte für Rotation, HMAC-SHA256-Blindindex für durchsuchbare Felder. Der Masterschlüssel wird niemals in der DB oder in DB-Backups gespeichert. - Datenbankhärtung: Minimales PostgreSQL,
scram-sha-256, TLS, zwei Rollen (Migrationseigentümer, Runtime nur DML), kein Superuser von der App, Alembic-Migrationen,statement_timeoutauf der Runtime-Rolle. - SQL-Konsole (falls vorhanden): Read-Only-Rolle, einzelnes
SELECT,statement_timeout, Zeilenlimit, gesperrte Konfiguration. - Kryptografie & Post-Quanten: AES-256-GCM im Ruhezustand ist quantenresistent. PQ-Readiness zielt auf Schlüsselaustausch und Signaturen: Hybrid-TLS
X25519MLKEM768auf dem Proxy; ML-KEM/ML-DSA (FIPS 203/204) nur, wo die Bibliothek diese unterstützt. Zufallswerte vonsecrets/crypto.getRandomValues. Niemals kryptografische Primitiven selbst implementieren. - Ausgehende Anfragen (SSRF): Jede UI-konfigurierbare URL (Webhooks, Syslog, LLM, OIDC) wird validiert: nur
https(es sei denn, explizite Allowlist), aufgelöste IP wird abgelehnt, wenn Loopback/Link-Local/Metadaten (169.254.0.0/16,fd00:ec2::254) oder privat, es sei denn, in der Allowlist, nach DNS-Auflösung erneut prüfen (DNS-ReBinding), keine Cross-Host-Weiterleitungen, strenge Timeouts. - Ausgehende Webhooks: Signiert mit HMAC-SHA256 (
X-Signature+ Zeitstempel), damit die Empfänger sie verifizieren können. - E-Mail: Header-Werte von CR/LF befreit; SMTPS mit Zertifikatsprüfung.
- Exporte: CSV/XLSX-Zellen, die mit
=,+,-,@, Tabulator oder CR beginnen, erhalten ein'als Präfix (Formel-Injection). - Ratenbegrenzung: Login, Passwort-Reset, MFA-Verifizierung, API-Schlüssel, Exporte, Uploads und teure Endpunkte.
- Antworten:
Cache-Control: no-storeauf authentifizierten API-Antworten. Allgemeine Fehlermeldungen mit einerrequest_id; Stacktraces nur in Logs. OpenAPI-UI in Produktion deaktiviert oder nur für Admins.
5. Autorisierung
- Standardmäßig verweigern: Jede Route deklariert ihre erforderliche Berechtigung; eine Route ohne Deklaration führt zu einem Fehler beim Start oder in Tests.
- RBAC mit Rollen, die auf Berechtigungen abgebildet werden (nicht direkt Rollen im Code prüfen).
- Objektbezogene Prüfungen (IDOR/BOLA): Eigentümer- oder Mandantenprüfung in der Repository-Schicht für jedes Lesen/Schreiben per ID. Unbefugter Zugriff auf ein vorhandenes Objekt gibt
404zurück. - Funktionsebenenprüfungen: Admin-Routen unter
/api/v1/admin/*werden durch eine einzige Abhängigkeit geschützt, niemals nur durch Ausblenden der UI. - Sensible Aktionen (Rollenänderungen, Schlüsselerstellung, Exporte, Löschung von Benutzern) erfordern eine kürzliche erneute Authentifizierung; optionale Vier-Augen-Genehmigung für Rolleneskalation zum Admin.
6. Datei-Uploads (falls vorhanden)
- Größenlimit auf Proxy- und App-Ebene; Allowlist von Erweiterungen und Magic-Byte-Prüfung.
- Außerhalb des Web-Roots (oder Objektspeicher) gespeichert, zufällige Dateinamen, mit
Content-Disposition: attachmentundX-Content-Type-Options: nosniffausgeliefert. - Bilder werden neu kodiert (entfernt EXIF und Polyglots); Archive werden auf Bomben und Path Traversal geprüft; optionaler Offline-Antivirus (ClamAV).
- SVG- und HTML-Uploads werden abgelehnt, es sei denn, sie werden bereinigt und von einer isolierten Herkunft ausgeliefert.
7. Logging, Audit & Administration
- Strukturierte Logs: JSON, Ebenen DEBUG/INFO/WARN/ERROR/CRITICAL,
request_idüberall, UTC-Zeitstempel, CR/LF aus Benutzerwerten entfernt. Passwörter, Token, Schlüssel, Sitzungs-IDs werden niemals protokolliert. - Remote-Syslog: RFC 5424 über TLS (RFC 5425) mit begrenztem lokalem Puffer; Host, Port, TLS, CA konfigurierbar über die Admin-UI. Kein rsyslog-Container.
- Fehlerbenachrichtigungen: SMTPS und Webhooks konfigurierbar über die Admin-UI, SSRF-validiert, "Test senden"-Schaltfläche, gedrosselt.
- PII-Maskierung: Middleware, die über die Admin-UI umgeschaltet werden kann.
- Manipulationssicherer Audit-Trail: Append-Only-Tabelle (Runtime-Rolle hat nur
INSERT/SELECT), jede Zeile ist mit dem Hash der vorherigen Zeile verkettet, an Syslog weitergeleitet. Umfasst Anmeldungen, Fehler, MFA-Änderungen, Rollenänderungen, Konfigurationsänderungen, Exporte, API-Schlüssel, Honeytoken-Treffer; zeichnet Benutzer, IP, User-Agent, UTC-Zeit und Vorher-/Nachher-Werte auf. - Admin-Dashboard: Nutzungsstatistiken, Fehler, Honeytoken-Warnungen, blockierte IPs.
- Geplante Hygiene: Inaktive Konten deaktivieren, abgelaufene Token/Sitzungen/Idempotenzschlüssel löschen, tägliche verschlüsselte Backups (Schlüssel getrennt vom Backup), Aufbewahrungsrichtlinie und ein getestetes Wiederherstellungsverfahren (
make restore-test). - Personenbezogene Daten (DSGVO): Aufbewahrungsfristen pro Datentyp, Benutzerdatenexport und -löschung, Bereinigungsjobs.
8. Authentifizierung, Identität & Aktive Verteidigung
- Passwörter: Argon2id (argon2-cffi-Standard / RFC 9106, Minimum m=19 MiB, t=2, p=1), beim Login erneut hashen, wenn sich die Parameter ändern. Richtlinie gemäß NIST SP 800-63B: ≥ 12 Zeichen, maximal ≥ 64, keine Zusammensetzungsregeln, abgelehnt, wenn in einer gebündelten Liste von kompromittierten/häufigen Passwörtern enthalten.
- Login: Identische Antwort und Zeitsteuerung für unbekannte Benutzer, progressive Verzögerungen + Drosselung pro Konto und pro IP (vermeidet harte Sperren, die DoS ermöglichen).
- Passwort-Reset: Einmaliger Zufalls-Token, der gehasht gespeichert wird, 30 Min. Gültigkeit, gleiche Antwort, unabhängig davon, ob das Konto existiert, alle Sitzungen werden nach dem Zurücksetzen widerrufen.
- Sitzungen: Serverseitig, Cookie
__Host-session(HttpOnly; Secure; SameSite=Lax; Path=/), ID wird bei Login und Berechtigungsänderung rotiert, Benutzer können ihre aktiven Sitzungen auflisten und widerrufen. Kein JWT im Browser-Speicher; wenn JWTs Dienst-zu-Dienst verwendet werden: Algorithmus fixiert,noneabgelehnt,aud/iss/expgeprüft, kurze Lebensdauer. - Admin-Sitzungen: 1 Stunde inaktiv, 8 Stunden absolut, erneute Authentifizierung für destruktive Aktionen.
- MFA: TOTP (gehashte Wiederherstellungscodes, Wiederholung desselben Codes abgelehnt) und WebAuthn/Passkeys. MFA für Admin-Konten obligatorisch.
- Kontexterkennung: Admin-Anmeldungen von unbekannten IPs/Geräten lösen eine "Neue Anmeldung"-Benachrichtigung aus und schränken destruktive Rechte bis zur MFA-Bestätigung ein.
- Bootstrap-Admin: Zufälliges Passwort, das beim ersten Start generiert wird, einmal lesbar über
make admin-password, erzwungener Reset + MFA-Registrierung beim ersten Login. - Break-Glass-Konto (optional): Lokaler Admin, der verwendet werden kann, wenn SSO ausfällt, standardmäßig deaktiviert, jede Verwendung löst einen kritischen Alarm aus.
- SSO: OIDC-Code-Flow + PKCE,
stateundnoncevalidiert, ID-Token-Signatur/aud/issgeprüft; LDAPS oder StartTLS mit Zertifikatsprüfung, LDAP-Filterwerte maskiert (LDAP-Injection). Verzeichnisgruppen werden Rollen zugeordnet. - SSO-Konfiguration, zwei gleichwertige Quellen: Jede OIDC- und LDAP(S)-Einstellung (Aktivierungs-Flag, Issuer/Server-URL, Client-ID, Scopes, Bind-DN, Basis-DN, Benutzer-/Gruppenfilter, CA-Bundle, Gruppen-zu-Rollen-Zuordnung, Auto-Provisioning) kann entweder über die Admin-UI oder über Umgebungsvariablen (
BACKEND_OIDC_*,BACKEND_LDAP_*) gesetzt werden.- Geheimnisse (
client_secret, Bind-Passwort) stammen von*_FILE-Variablen oder dem Secrets-Provider, niemals als einfache Umgebungsvariablen in der Produktion; in der UI sind sie schreibgeschützt (••••letzte4). - Rangfolge: Eine durch die Umgebung definierte Einstellung gewinnt und wird in der Admin-UI schreibgeschützt mit einem "Von Umgebung verwaltet"-Badge angezeigt; alles andere ist bearbeitbar und wird verschlüsselt in der Datenbank gespeichert.
- Gleiche Validierung für beide Quellen (Pydantic-Schema, das von env-Loader und Admin-API gemeinsam genutzt wird); ungültige Umgebungskonfiguration lässt den Start mit einem klaren Fehler fehlschlagen, ungültige UI-Eingabe wird vor dem Speichern abgelehnt.
- Die Admin-UI hat eine "Verbindung testen"-Aktion (OIDC-Discovery + JWKS-Abruf, LDAP-Bind + Beispiel-Gruppensuche) und jede Änderung wird auditiert.
- Jeder...
- Geheimnisse (