From d15774f1cdc5d928b01f0cd020cc7a7bfd29d38e Mon Sep 17 00:00:00 2001 From: Debian Date: Sun, 5 Jul 2026 22:31:42 +0200 Subject: [PATCH] =?UTF-8?q?fix(security):=20x/crypto=20v0.52=20+=20x/net?= =?UTF-8?q?=20v0.55=20(6=20CVEs)=20+=20govulncheck-Release-Gate=20?= =?UTF-8?q?=E2=80=94=20v1.3.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit govulncheck ab sofort fest im Release-Prozess. Baseline-Scan fand 6 aktiv aufgerufene Vulns (SSH-Backup-Pfad internal/services/backup/remote): - 5× golang.org/x/crypto (SSH DoS/Deadlock/Panic: GO-2026-5013/5017/5018/5019/5020) → x/crypto v0.51.0 => v0.52.0 - 1× golang.org/x/net (GO-2026-5026) → v0.53.0 => v0.55.0 Re-Scan danach: "No vulnerabilities found." Go-Quality-Baseline (Makefile + .golangci.yml, portabel): - release-check läuft autom. vor jedem deb/publish: vet → golangci-lint (Rollout: non-blocking) → govulncheck (HARTER Gate) → build → test -race. - make vulncheck / make test-race als eigene Targets. - .golangci.yml: staticcheck/govet/errcheck/ineffassign/unused/misspell + gosec/bodyclose/rowserrcheck/sqlclosecheck/noctx/contextcheck. - go test -race: aktuell 0 Races (Gate sicher). Doku in CLAUDE.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- .golangci.yml | 42 ++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 16 ++++++++++++++-- Makefile | 34 ++++++++++++++++++++++++++++++---- VERSION | 2 +- go.mod | 6 +++--- go.sum | 12 ++++++------ 6 files changed, 96 insertions(+), 16 deletions(-) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..81ed290 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,42 @@ +# Go-Quality-Baseline für EdgeGuard (portabel für weitere Go-Projekte). +# Rollout: erst NON-BLOCKING laufen lassen (Bestand aufräumen), dann in der +# CI/Makefile auf harten Gate stellen. govulncheck ist bereits ein harter +# Release-Gate (siehe Makefile: vulncheck / release-check). +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 + - rowserrcheck # fehlendes rows.Err() (database/sql-Muster) + - sqlclosecheck # fehlendes rows/stmt.Close() + # ── 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 + +# HINWEIS: rowserrcheck/sqlclosecheck zielen auf database/sql. EdgeGuard nutzt +# pgx/pgxpool — dort greifen sie nur teilweise. Das pgx-Muster (manuelles +# rows.Next()/Scan() + defer rows.Close() + rows.Err()) bitte weiter per Review +# absichern; siehe internal/services/*/*.go. diff --git a/CLAUDE.md b/CLAUDE.md index 7f0f9e0..e051036 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -131,8 +131,11 @@ HAProxy terminiert TLS auf `:443`, routet per Host-Header an Backends und fällt ```bash make build # Host-Architektur (amd64) make test # go test ./... -make lint # golangci-lint -make deb # amd64 + arm64 .deb +make test-race # go test -race ./... (Race-Detector) +make lint # go vet + golangci-lint +make vulncheck # govulncheck ./... (Go-Vuln-DB-Scan) +make release-check # Go-Quality-Baseline (läuft autom. vor jedem deb/publish) +make deb # amd64 + arm64 .deb (führt release-check aus) make publish # deb + Upload Gitea Package Registry make install-local # direkt auf Dev-Server installieren (kein .deb) @@ -140,6 +143,15 @@ make install-local # direkt auf Dev-Server installieren (kein .deb) cd management-ui && bun install && bun run build ``` +### Go-Quality-Baseline (PFLICHT vor jedem Release) +`make deb`/`make publish` führen automatisch `release-check` aus — Reihenfolge: +**`go vet` → `golangci-lint run` → `govulncheck ./...` → `go build` → `go test -race`**. + +- **`govulncheck` ist ein HARTER Gate** — Build bricht ab, wenn der Code eine bekannte CVE tatsächlich aufruft. Tool wird bei Bedarf autom. installiert. Zusätzlich sinnvoll: wöchentlicher CI-Cron (CVEs tauchen auch ohne Code-Änderung auf). +- **`golangci-lint`** (`.golangci.yml`: staticcheck, govet, errcheck, ineffassign, unused, misspell, **gosec**, **bodyclose**, rowserrcheck, sqlclosecheck, noctx, contextcheck) läuft im **Rollout noch NON-BLOCKING** (Bestand aufräumen), danach auf harten Gate stellen. +- **`go test -race`** — Race-Detector; findet Nebenläufigkeits-Bugs (Scheduler/Worker), die normale Tests durchlassen. +- Portabel als „Go-Quality-Baseline" für weitere Go-Projekte gedacht. + --- ## Dev-Server Quickstart diff --git a/Makefile b/Makefile index 26fa481..660f39e 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ LDFLAGS := -s -w -X main.version=$(VERSION) GOFLAGS := -trimpath -mod=readonly export CGO_ENABLED ?= 0 -.PHONY: all help build test lint tidy clean ui \ +.PHONY: all help build test test-race lint vulncheck release-check tidy clean ui \ build-linux-amd64 build-linux-arm64 \ deb deb-amd64 deb-arm64 \ publish publish-amd64 publish-arm64 @@ -61,9 +61,35 @@ build-linux-arm64: test: $(GO) test $(GOFLAGS) ./... +test-race: + CGO_ENABLED=1 $(GO) test $(GOFLAGS) -race ./... + lint: $(GO) vet ./... - @command -v staticcheck >/dev/null && staticcheck ./... || echo "staticcheck not installed, skipping" + @command -v golangci-lint >/dev/null 2>&1 && golangci-lint run \ + || echo "golangci-lint nicht installiert (go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest) — übersprungen" + +GOBIN := $(shell $(GO) env GOPATH)/bin + +# govulncheck — Go-Vuln-DB-Scan. HARTER Release-Gate: bricht ab, wenn der +# Code eine bekannte Vulnerability tatsächlich aufruft. Tool wird bei Bedarf +# automatisch installiert. +vulncheck: + @command -v govulncheck >/dev/null 2>&1 || GOFLAGS= $(GO) install golang.org/x/vuln/cmd/govulncheck@latest + @PATH="$(GOBIN):$$PATH" govulncheck ./... + +# Go-Quality-Baseline — läuft automatisch vor jedem Release (deb/publish). +# Reihenfolge: vet → golangci-lint (Rollout: NON-BLOCKING) → govulncheck (GATE) +# → build → test -race. govulncheck bricht bei jedem Fund ab; der Linter ist +# in der Rollout-Phase noch non-blocking (Bestand aufräumen, dann auf Gate). +release-check: + $(GO) vet ./... + @command -v golangci-lint >/dev/null 2>&1 && (golangci-lint run || echo " ⚠ golangci-lint-Findings (non-blocking, Rollout-Phase)") \ + || echo " golangci-lint nicht installiert — übersprungen (Rollout-Phase)" + @$(MAKE) --no-print-directory vulncheck + $(GO) build ./... + CGO_ENABLED=1 $(GO) test $(GOFLAGS) -race ./... + @echo " ✓ Go-Quality-Baseline bestanden (vet, govulncheck, build, test -race)" tidy: $(GO) mod tidy @@ -74,10 +100,10 @@ ui: if [ -x "$$(command -v bun)" ]; then bun install --silent && bun run build; \ else npm install --silent && npm run build; fi -deb-amd64: build-linux-amd64 ui +deb-amd64: release-check build-linux-amd64 ui @./scripts/apt-repo/build-package.sh amd64 $(VERSION) -deb-arm64: build-linux-arm64 ui +deb-arm64: release-check build-linux-arm64 ui @./scripts/apt-repo/build-package.sh arm64 $(VERSION) deb: deb-amd64 deb-arm64 diff --git a/VERSION b/VERSION index 589268e..6261a05 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.0 \ No newline at end of file +1.3.1 \ No newline at end of file diff --git a/go.mod b/go.mod index e5aacea..dfffeaa 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/pquerna/otp v1.5.0 github.com/pressly/goose/v3 v3.27.1 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/crypto v0.51.0 + golang.org/x/crypto v0.52.0 golang.org/x/oauth2 v0.36.0 ) @@ -79,9 +79,9 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/mod v0.35.0 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/net v0.55.0 // indirect golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.44.0 // indirect + golang.org/x/sys v0.45.0 // indirect golang.org/x/text v0.37.0 // indirect golang.org/x/tools v0.44.0 // indirect google.golang.org/protobuf v1.36.11 // indirect diff --git a/go.sum b/go.sum index 492eaf4..167885c 100644 --- a/go.sum +++ b/go.sum @@ -186,18 +186,18 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= -golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= +golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=