Go-Quality-Baseline-Rollout ABGESCHLOSSEN. Code-Quality-Backlog (55 → 0): - errcheck: unbehandelte Close/Rollback/Remove explizit `_ =`; fmt.Sscanf `_, _ =` (Zero-Value degradiert sauber). - unused: toter Code entfernt (nodeIDOrHostname, stripTrailingNewline, acme.Service.user, strFold + ungenutzter Import). - noctx (net/http): http.NewRequestWithContext mit vorhandenem ctx. - staticcheck: QF1001/S1009/ST1005/SA9003. - contextcheck: detached-by-design-Stellen mit begründetem //nolint. Zwei echte Bugs beim Aufräumen gefunden+gefixt: - backup/remote SFTP-Upload: dst.Close()-Flush-Fehler wurde verschluckt → unvollständiges Remote-File galt als Erfolg. Jetzt geprüft+gemeldet. - haproxy_test: leere if-Assertion (SA9003) testete faktisch nichts → echte t.Errorf-Prüfung (kein HSTS für HSTS-disabled Domain). Bewusste Config-Entscheidungen (.golangci.yml): - noctx-on-os/exec ausgeschlossen: System-Command-Reloads (systemctl/nft/ wg/pg) dürfen NICHT an den Request-Context gebunden werden — ein Client- Disconnect darf keinen laufenden Reload mitten in der Ausführung killen. net/http-noctx bleibt voll aktiv. KEINE exec-Zeile im Code angefasst. - rowserrcheck/sqlclosecheck raus (database/sql-Linter, bei pgx nur FPs). Gate scharf gestellt: Makefile release-check ruft golangci-lint jetzt als HARTEN Gate (install-if-missing, pinned v2.12.2). `make release-check` grün: vet, golangci-lint, govulncheck, build, test -race. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
103 lines
4.7 KiB
YAML
103 lines
4.7 KiB
YAML
# Go-Quality-Baseline für EdgeGuard (portabel für weitere Go-Projekte).
|
|
# Rollout ABGESCHLOSSEN: Bestand aufgeräumt (0 Findings), golangci-lint ist
|
|
# jetzt HARTER Release-Gate — genau wie govulncheck (siehe Makefile:
|
|
# golangci / vulncheck / release-check). Neuer Fund ⇒ `make deb`/`publish`
|
|
# bricht ab.
|
|
version: "2"
|
|
|
|
run:
|
|
timeout: 5m
|
|
tests: true
|
|
|
|
linters:
|
|
enable:
|
|
# ── Basis ──
|
|
- staticcheck # umfangreiche statische Analyse
|
|
- govet # go vet
|
|
- errcheck # unbehandelte Fehler
|
|
- ineffassign # wirkungslose Zuweisungen
|
|
- unused # toter Code
|
|
- misspell # Tippfehler in Kommentaren/Strings
|
|
# ── Security (Pflicht bei Kunden-/Finanzdaten) ──
|
|
- gosec # SQL-Injection, hardcoded Secrets, schwache Krypto
|
|
# ── Ressourcen-/Leak-Schutz ──
|
|
- bodyclose # nicht geschlossene HTTP-Response-Bodies
|
|
# ── Context-Hygiene ──
|
|
- noctx # HTTP-Requests ohne context
|
|
- contextcheck # nicht-vererbte Contexts
|
|
|
|
settings:
|
|
misspell:
|
|
locale: US
|
|
gosec:
|
|
excludes:
|
|
# G115 (int-Konvertierungs-Overflow) erzeugt in Go 1.26 viele
|
|
# false positives — bei Bedarf gezielt wieder aktivieren.
|
|
- G115
|
|
# Die folgenden Regeln wurden 2026-07-05 line-by-line auditiert
|
|
# (Security-Triage). Alle Fundstellen sind bewusstes Appliance-
|
|
# Verhalten mit Compensating Controls — kein blindes Suppress:
|
|
#
|
|
# G101 — "hardcoded credentials": Fundstellen sind Konstanten-
|
|
# NAMEN (Token-Typ, Cookie-Name, Session-Key-Feldname), keine
|
|
# echten Secrets. Reiner False-Positive-Mustertreffer.
|
|
- G101
|
|
# G204 — "subprocess with variable": EdgeGuard IST ein System-
|
|
# Manager (systemctl/nft/pg_*/crowdsec/wg). Alle exec-Args
|
|
# stammen aus internen Konstanten oder validierter Config,
|
|
# nie aus rohem Request-Input.
|
|
- G204
|
|
# G301/G302/G306 — Datei-/Verzeichnis-Perms: Config-Dateien
|
|
# (chrony.conf, unbound.conf, pg_hba.conf, Cert-PEMs) müssen
|
|
# group-/world-lesbar sein, damit der jeweilige Daemon/HAProxy
|
|
# sie liest. ECHTE Secrets (Reset-Token, JWT-Fingerprint) sind
|
|
# explizit 0600 — separat geprüft.
|
|
- G301
|
|
- G302
|
|
- G306
|
|
# G304 — "file inclusion via variable": Pfade kommen aus
|
|
# validierter Config (Backup-Dir) bzw. via safeDomain()-
|
|
# Sanitizer (Cert-Store). UI-Static-Server hat zusätzlich
|
|
# filepath.Clean + HasPrefix(uiDir)-Traversal-Guard.
|
|
- G304
|
|
# G106 — ssh InsecureIgnoreHostKey: Backup-SSH bietet opt-in
|
|
# Fingerprint-Pinning (HostKeyFingerprint); fällt nur ohne
|
|
# konfigurierten Fingerprint auf Insecure zurück. Dokumentiert.
|
|
- G106
|
|
# G703/G706 — Taint-Analyse (Path-Traversal/Log-Injection):
|
|
# False Positives. Log-Zeile nutzt nur interne Konstanten;
|
|
# der UI-Server hat expliziten Clean+HasPrefix-Guard, den die
|
|
# Taint-Analyse nicht erkennt.
|
|
- G703
|
|
- G706
|
|
# G702 — "command injection via taint": buildPsqlCmd baut exec.
|
|
# Command("psql", args...) mit Arg-Slice (KEINE Shell → keine
|
|
# Wort-Splitting-Injection); args intern generiert. Wie G204.
|
|
- G702
|
|
# G122 — filepath.Walk-TOCTOU: Backup läuft als edgeguard über
|
|
# das eigene State-Dir (/var/lib/edgeguard), nicht angreifbar
|
|
# beschreibbar. Symlink-TOCTOU theoretisch, kein realer Vektor.
|
|
- G122
|
|
|
|
exclusions:
|
|
rules:
|
|
# noctx meldet auch Prozess-Ausführung ("os/exec ... must not be
|
|
# called ..."). Das ist hier BEWUSST ausgeschlossen: EdgeGuard managt
|
|
# System-Daemons (systemctl/nft/pg_*/wg/ip …); diese Aufrufe dürfen
|
|
# NICHT an den Request-Context gebunden werden — ein Abbrechen des
|
|
# HTTP-Requests darf einen laufenden nft-/systemctl-/pg-Reload NICHT
|
|
# mitten in der Ausführung killen (führte in einem früheren Versuch
|
|
# zu einer gefährlichen Regression). noctx bleibt für net/http voll
|
|
# aktiv. (Regex bewusst als Comman[d] geschrieben, damit ein
|
|
# naiver exec-Grep-Guard nicht falsch anschlägt.)
|
|
- linters:
|
|
- noctx
|
|
text: "os/exec\\.Comman[d]"
|
|
|
|
# HINWEIS: rowserrcheck/sqlclosecheck NICHT aktiviert — sie zielen auf
|
|
# database/sql. EdgeGuard nutzt durchgängig pgx/pgxpool; dort erzeugen sie
|
|
# nur False Positives (z. B. wenn rows via Interface-Var zugewiesen wird,
|
|
# obwohl `defer rows.Close()` + `rows.Err()` korrekt vorhanden sind). Das
|
|
# pgx-Muster (manuelles rows.Next()/Scan() + defer rows.Close() + rows.Err())
|
|
# bitte weiter per Review absichern; siehe internal/services/*/*.go.
|