Lektion 5.2

Security-Essentials: Rate Limits, CSP-Header, Key-Verschlüsselung, Pre-Public-Repo-Audits

Kern-Sicherheitsmassnahmen anwenden, damit deine App Missbrauch widersteht und nie sensible Daten leakt

26 minQualität, Sicherheit und das agent-first BusinessVerfügbar

Was du lernst

  • Jeden öffentlichen Endpunkt rate-limiten, um Brute Force, Spam und rechnungsfressenden Missbrauch zu stoppen
  • CSP-Header, gespeicherte Credentials verschlüsseln und ein Audit-Log führen
  • Eine Pre-Public-Repo-Checkliste, damit Secrets in der Historie nie öffentlich werden

Überblick

In dem Moment, in dem deine App im öffentlichen Internet ist, wird sie innerhalb von Minuten von Bots abgetastet. Du brauchst kein Security-Team, um gegen die gängigen Angriffe sicher zu sein, du brauchst eine Handvoll Essentials, konsequent angewandt: deckle jeden öffentlichen Endpunkt mit einem Rate Limit, sperre mit einer CSP ab, was der Browser ausführen wird, verschlüssele die Credentials, die du speicherst, logge, wer was getan hat, und schalte nie ein Repo auf öffentlich, ohne seine Historie auf Secrets zu auditieren. Diese Lektion macht jedes davon konkret.

Was du lernst

Du lernst, öffentlichen Endpunkten Rate Limits hinzuzufügen, einen Content-Security-Policy-Header zu setzen, gespeicherte Credentials at rest zu verschlüsseln, ein nützliches Audit-Log zu führen und ein Pre-Public-Repo-Audit zu fahren, das Secrets fängt, die sich in alten Commits verstecken. Das sind die Massnahmen, die ein Hobbyprojekt von etwas trennen, auf das du verantwortungsvoll echte Nutzer richten kannst.

Voraussetzungen

Die Secrets-Lektionen aus Kurs 1 und 3, da mehrere Massnahmen hier darauf aufbauen, Secrets in Umgebungsvariablen und aus dem Code herauszuhalten. Eine deploytе App mit mindestens einem öffentlichen Endpunkt oder Formular macht die Lektion konkret, aber du kannst alles ab dem ersten Commit auf dein nächstes Projekt anwenden.

Das Problem

Drei Versäumnisse schaden kleinen Bauenden immer wieder. Erstens: ein ungeschützter Endpunkt wird gehämmert - ein Login-Formular brute-forced, ein Kontaktformular zugespammt oder ein KI-Endpunkt in einer Schleife aufgerufen, bis deine Anbieter-Rechnung explodiert. Zweitens: ein gespeicherter API-Key oder ein Passwort sitzt im Klartext, sodass ein einziges Datenbank-Leak einem Angreifer alles in die Hand gibt. Drittens, und am häufigsten: eine Gründerin macht ein Repo öffentlich, um es zu teilen, und ein vor zwei Jahren committetes Secret ist jetzt für immer im offenen Internet. Jedes ist mit einer Gewohnheit vermeidbar.

Rate-limite jeden öffentlichen Endpunkt

Ein Rate Limit deckelt, wie oft ein einzelner Client einen Endpunkt in einem Zeitfenster treffen kann. Es ist die günstigste, hebelstärkste Security-Kontrolle, die du hast, und jeder Endpunkt, den ein Fremder erreichen kann, braucht eines: Login, Signup, Passwort-Reset, Kontaktformulare und vor allem jeder Endpunkt, der dich pro Aufruf Geld kostet, etwa einer, der ein LLM auslöst. Limitiere per IP für anonymen Traffic und per Nutzer oder API-Key für authentifizierten Traffic. Wenn das Limit überschritten wird, gib ein 429 zurück und stopp.

// Ein minimaler Fixed-Window-Limiter. In Produktion nutze einen geteilten Store
// (Redis, Upstash oder deine DB), damit er über mehrere Server hinweg funktioniert.
const hits = new Map<string, { count: number; resetAt: number }>()

export function rateLimit(key: string, max = 10, windowMs = 60_000) {
  const now = Date.now()
  const entry = hits.get(key)
  if (!entry || now > entry.resetAt) {
    hits.set(key, { count: 1, resetAt: now + windowMs })
    return { ok: true }
  }
  if (entry.count >= max) return { ok: false, retryAfter: entry.resetAt - now }
  entry.count += 1
  return { ok: true }
}

// In deinem Handler:
// const limit = rateLimit(`login:${ip}`, 5, 60_000)
// if (!limit.ok) return new Response('Too many requests', { status: 429 })
Eine Rate-Limiter-Skizze - deckle per IP für anonymen Traffic, per Nutzer oder Key für authentifizierten

CSP-Header und gespeicherte Credentials verschlüsseln

Eine Content Security Policy sagt dem Browser genau, welche Quellen für Scripts, Styles und Bilder er laden darf. Es ist deine stärkste Verteidigung gegen Cross-Site-Scripting: selbst wenn ein Angreifer ein script-Tag einschleust, weigert sich der Browser, es auszuführen, weil die Quelle nicht auf deiner Allowlist steht. Starte streng und lockere nur, was du musst. Separat sollte alles Sensible, das du speicherst - ein Drittanbieter-API-Key, ein OAuth-Token, ein Nutzer-Secret - at rest verschlüsselt sein, sodass ein Datenbank-Einbruch Chiffretext liefert, keine funktionierenden Credentials. Der Verschlüsselungs-Key selbst lebt in einer Umgebungsvariable, nie in der Datenbank, die er schützt.

Content-Security-Policy: default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.your-provider.com;
  frame-ancestors 'none';
  base-uri 'self'
Eine CSP zum Start - standardmässig self, dann nur erlauben, was deine App wirklich braucht
  • default-src 'self' heisst: sofern nicht anders angegeben, nur von deiner eigenen Domain laden.
  • connect-src kontrolliert, welche APIs der Browser aufrufen darf - liste nur deine echten Backends.
  • frame-ancestors 'none' stoppt andere Sites, deine in einem iframe einzubetten (Clickjacking).
  • Verschlüssele gespeicherte Secrets mit einer Library, nicht von Hand; halt den Key in einer Env-Var, rotiere ihn, falls er je leakt.

Audit-Logs: wissen, wer was getan hat

Wenn etwas schiefgeht - eine Erstattung ausgestellt, ein Account gelöscht, ein Plan herabgestuft - musst du beantworten "wer hat das getan, wann und von wo". Ein Audit-Log ist eine nur-anhängende Aufzeichnung sensibler Aktionen: der Akteur, die Aktion, das Ziel, ein Zeitstempel und die Quell-IP. Es ist nicht dasselbe wie deine Anwendungs-Logs; es ist eine bewusste Spur für Security und Verantwortlichkeit. Logge jede Aktion, die Geld bewegt, Berechtigungen ändert oder die Daten eines anderen Nutzers berührt. Logge nie die Secrets selbst, nur, dass die Aktion passiert ist.

Die Pre-Public-Repo-Checkliste

Das ist die, die am härtesten beisst. Einen Key aus deinem neuesten Commit zu löschen entfernt ihn nicht aus der Historie - er sitzt immer noch in einem alten Commit, den jeder lesen kann, sobald das Repo öffentlich geht. Bevor du irgendein Repo von privat auf öffentlich schaltest, geh diese Checkliste jedes Mal durch. Wenn du ein Secret in der Historie findest, ist der einzige sichere Zug, dieses Secret als kompromittiert zu behandeln: rotiere es sofort, dann scrubbe die Historie.

  • Scanne die volle Historie auf Secrets, nicht nur die aktuellen Dateien. Nutze ein Tool wie gitleaks oder trufflehog: gitleaks detect --source . fängt Keys, Tokens und Passwörter über jeden Commit.
  • Bestätige, dass .env und jede Secret-Datei in .gitignore sind und nie committet wurden.
  • Prüfe auf hardcodete Keys, interne URLs, Kundendaten und Credentials in Code und Kommentaren.
  • Wenn je ein Secret committet wurde: rotiere es zuerst (nimm an, es ist schon öffentlich), dann schreib die Historie um, um es zu entfernen, bevor du öffentlich gehst.
  • Erst nach einem sauberen Scan schaltest du das Repo auf öffentlich.
# Audite die ganze Git-Historie auf geleakte Secrets, bevor du öffentlich gehst
gitleaks detect --source . --verbose

# Wenn etwas gefunden wird, ROTIERE das Secret zuerst, dann scrubbe die Historie.
Lass das vor jedem Privat-zu-Öffentlich-Wechsel laufen - die Historie überlebt eine Löschung

Typische Fehler

Die wiederkehrenden: einen KI- oder E-Mail-Endpunkt ohne Rate Limit ausliefern und mit einer fünfstelligen Rechnung aufwachen; Drittanbieter-Tokens im Klartext speichern, sodass ein Leak jeden verbundenen Account kompromittiert; die CSP überspringen, weil sie fummelig ist, und dann ein XSS schlucken; und der Klassiker - ein Repo auf öffentlich schalten, um "das Projekt zu teilen", ohne die Historie zu auditieren, und einen Key leaken, der seit Monaten dort liegt. Jedes wird durch eine Gewohnheit in dieser Lektion verhindert.

Business-ROI

Security ist unsichtbar, wenn sie funktioniert, und katastrophal, wenn nicht. Ein geleakter Key kann ein Budget über Nacht leersaugen, ein Einbruch in gespeicherte Credentials kann ein Unternehmen beenden, und ein einziges Public-Repo-Leak hat Gründer echtes Geld und echte Kunden gekostet. Die Essentials hier kosten dich einen Nachmittag zum Aufsetzen und laufen dann für immer. Für ein agent-getriebenes Team zählt das doppelt: Agents generieren Endpunkte schnell, also muss die Disziplin von "jeder öffentliche Endpunkt bekommt ein Rate Limit, jedes Secret wird verschlüsselt, jedes Repo wird auditiert" eine Regel sein, der der Agent folgt, nicht etwas, an das du dich erinnerst.

Checkliste

Bestätige jedes davon, bevor du echte Nutzer auf irgendetwas richtest, das du gebaut hast.

  • Jeder öffentliche und geldausgebende Endpunkt hat ein Rate Limit, das bei Überschreitung 429 zurückgibt.
  • Ein Content-Security-Policy-Header ist gesetzt und so streng, wie deine App es erlaubt.
  • Gespeicherte Credentials und Tokens sind at rest verschlüsselt, mit dem Key in einer Env-Var.
  • Du hast einen Vollhistorie-Secret-Scan vor jedem öffentlichen Repo gefahren und alles Gefundene rotiert.

Ressourcen

Halt gitleaks oder trufflehog installiert und füge den Historie-Scan zu deinem Pre-Public-Ritual hinzu. Die OWASP Top 10 und MDNs CSP-Referenz sind die zeitlosen Quellen, wenn du Tiefe brauchst. Pack "rate-limite diesen Endpunkt" und "verschlüssele dieses gespeicherte Secret" in deine Projektregeln, sodass Agents sie ungefragt anwenden.

Deine Aufgabe

Füge einem echten Endpunkt ein Rate Limit hinzu und bestätige, dass es 429 zurückgibt, wenn du es überschreitest. Setz einen CSP-Header auf deine App und behebe, was er bricht, bis die Seite unter einer strengen Policy funktioniert. Dann fahr gitleaks gegen eines deiner Repos und lies den Output - selbst ein sauberes Ergebnis lehrt dich, der Prüfung zu trauen, bevor du je öffentlich gehst.

Nächste Lektion

Sicher und gehärtet, behandelt die nächste Lektion Recht und Compliance: DSGVO, rechtskonforme Cookie-Einwilligung inklusive Global Privacy Control und die US- und Schweizer Datenschutzgesetze, erklärt ohne Kopfweh.

Kommentare

Kommentare werden geladen.

Kommentar schreiben
KommentareWeiter
Nächster Schritt

Bereit, KI als Workflow zu nutzen?

Starte mit dem Starter-Pfad, speichere deinen Fortschritt lokal und synchronisiere alles später kostenlos mit deinem Konto.