Files
nexarch/docs/CODING-GUIDELINES-CORE.md
T

4.4 KiB
Raw Blame History

NEXARCH Core Projektweite Sicherheits-Coding-Konventionen

Stand: 2026-08-28. Ticket: IAM-15. Ergänzt docs/TESTSTRATEGIE-CORE.md (QA-01) um Coding-Regeln, die als Code-Review-Checkliste gelten — keine dieser Regeln ist optional oder "nur für ein Modul".

1. Warum dieses Dokument existiert

Eine sicherheitsrelevante Coding-Regel, die nur einmal an einer Stelle vorgemacht statt projektweit verankert wird, wird beim nächsten neuen Vergleich vergessen. Das gilt für jede Regel in diesem Dokument gleichermaßen — die erste Regel (SQL) ist bereits als Konvention etabliert, die zweite (timing-safe Vergleich, IAM-15) macht sie hier zum ersten Mal explizit schriftlich.

2. Regel: Kein fmt.Sprintf für SQL-Bestandteile aus Nutzereingabe

Spalten-/Tabellennamen ausschließlich aus statischen Konstanten bzw. einem geschlossenen Enum/Switch-Typ, nie aus Nutzereingabe oder generischem String-Zusammenbau — auch nicht hinter einer Whitelist-Funktion. Werte (nicht Bezeichner) gehören als Parameter ($1, $2, …) in die Query, niemals interpoliert.

Lehre aus beiden Altsystemen (known-issues-archivdms.md Punkt 10, known-issues-archivmail.md Punkt 12): dynamische Tabellennamen via fmt.Sprintf, nur durch eine fragile Whitelist-Funktion abgesichert. Siehe DMS/Mail SRC-11 für die board-spezifische Umsetzung dieser Regel im Suchindex-Kontext.

Referenzbeispiel (korrekt): internal/tenant/lifecycle.go, ProcessDueDeletions — Statuswerte und IDs ausschließlich als Parameter ($1, $2, …), niemals interpoliert; der einzige Einsatz von fmt.Sprintf im Package baut einen Datenbanknamen aus einem bereits validierten Slug (dbNameForSlug, slugPattern in tenant.go erzwingt ^[a-z][a-z0-9_]{1,48}$ vor jeder Verwendung) — keine ungeprüfte Nutzereingabe erreicht die Query.

3. Regel: Timing-safe Vergleich für jede sicherheitsrelevante Zugriffsentscheidung (IAM-15)

Jeder Vergleich, der eine sicherheitsrelevante Zugriffsentscheidung trifft — Passwort-Hash, Token, Signatur, 2FA-Code/-Wiederherstellungscode — nutzt einen timing-safe/constant-time Vergleich, nie den regulären ==-Operator. Ein naiver ==-Vergleich zweier Byte-Folgen bricht bei der ersten abweichenden Stelle ab; die dadurch messbare Laufzeitdifferenz lässt sich aus der Ferne ausmessen und erlaubt ein Byte-für-Byte-Erraten des korrekten Werts (Timing-Angriff).

So wird es gemacht: internal/timingsafe (dieses Ticket) bündelt die kanonische Implementierung (crypto/subtle.ConstantTimeCompare) für neue Vergleichsstellen:

import "gitea.perlbach24.de/scripte/nexarch/internal/timingsafe"

if !timingsafe.EqualString(providedCode, expectedCode) {
    return ErrInvalid
}

Ausnahme: bcrypt.CompareHashAndPassword (Passwort-Hashes) ist bereits von Haus aus timing-safe — hier ist kein zusätzlicher Wrapper nötig.

3.1 Audit bestehender Vergleichsstellen (Prüfung 2)

Durchgeführt 2026-08-28, Ergebnis: alle bestehenden sicherheitsrelevanten Vergleichsstellen implementierten die Regel bereits korrekt, unabhängig voneinander mit crypto/subtle — nichts musste korrigiert werden (Akzeptanzkriterium 3, „ggf.").

Ort Was wird verglichen Fundstelle
internal/totp/totp.go, Validate TOTP-Code (2FA) nutzte bereits subtle.ConstantTimeCompare direkt, in diesem Ticket auf timingsafe.EqualString umgestellt (erster Verwender des neuen Packages)
internal/webhook/dispatcher.go, VerifySignature HMAC-Webhook-Signatur subtle.ConstantTimeCompare(expectedBytes, gotBytes)
internal/moduleregistry/credentials.go, Authenticate Service-Credential-Secret-Hash eigene timingSafeEqual-Hilfsfunktion, gleiches Muster
internal/authtoken/token.go, Consume (Passwort-Reset/Einladung) Einmal-Token Hash-Lookup über DB-Index (WHERE token_hash = $1), kein manueller Byte-Vergleich nötig — bei zufälligen, hochentropischen Token ist der indexierte Hash-Abgleich gleichwertig sicher

Neue Vergleichsstellen sollen internal/timingsafe verwenden, statt das Muster erneut inline zu duplizieren — bestehende Stellen müssen dafür nicht umgebaut werden (kein Umbau angrenzender Bereiche über Board-Branch-Grenzen hinweg).

4. Wie diese Liste wächst

Neue projektweite Sicherheits-Coding-Regeln werden hier ergänzt, sobald sie (wie SQL-Sprintf und timing-safe Vergleich) mehr als einmal unabhängig als Lehre auftauchen — nicht vorab spekulativ.