Files
edgeguard-native/.golangci.yml
Debian 32ab2c7f47 chore(lint): Backlog auf 0 + golangci-lint als HARTER Gate — v1.3.3
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>
2026-07-06 00:49:07 +02:00

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.