From a42ec0b26827f1f0b408982922e19aed72d5f9b4 Mon Sep 17 00:00:00 2001 From: Vortex Dispatch Date: Thu, 16 Jul 2026 04:29:00 +0200 Subject: [PATCH] security(scan): Go 1.26.5 (crypto/tls CVE), x/sys bump, Slowloris timeouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post-P0 adversarial re-scan (govulncheck + gosec) findings, all fixed: - Go 1.26.4 → 1.26.5: clears GO-2026-5856 (Encrypted Client Hello privacy leak in crypto/tls) — reachable from the web dashboard server, ghost client, and improve scrapers. govulncheck now reports 0 vulnerabilities affecting our code. - golang.org/x/sys v0.36.0 → v0.44.0: clears GO-2026-5024 (integer overflow in NewNTUnicodeString, windows-only, not called by our code — hygiene bump). - ReadHeaderTimeout: 10s on both the web dashboard and memory dashboard http.Servers (gosec G112 Slowloris). - Annotated three gosec false positives with rationale: G101 on FIGMA_TOKEN env-var NAME and the public figma.com settings URL; G703 on copyDesignDir (os.ReadDir base names cannot contain separators). Remaining gosec MEDIUM/LOW volume (G204 subprocess, G304 file inclusion, G301/G306 perms, G104 best-effort discards) is the documented accepted baseline for a subprocess-orchestration tool — golangci-lint remains at 0 issues. go vet clean; full go test ./... -count=1 green on go1.26.5. Co-Authored-By: Claude Fable 5 --- go.mod | 4 ++-- go.sum | 4 ++-- internal/cli/figma.go | 2 +- internal/engine/design_context.go | 2 +- internal/figma/token.go | 2 +- internal/memory/server.go | 3 ++- internal/web/server.go | 5 ++++- 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 11545c3..deef1f4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/tzone85/vortex-dispatch -go 1.26.4 +go 1.26.5 require ( github.com/charmbracelet/bubbletea v1.3.10 @@ -11,7 +11,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.34 github.com/oklog/ulid/v2 v2.1.1 github.com/spf13/cobra v1.10.2 - golang.org/x/sys v0.36.0 + golang.org/x/sys v0.44.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 0018427..188bb0b 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ 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.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +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/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/cli/figma.go b/internal/cli/figma.go index bf05b94..03fc754 100644 --- a/internal/cli/figma.go +++ b/internal/cli/figma.go @@ -11,7 +11,7 @@ import ( // figmaTokenSettingsURL is where a personal access token is created. Printed, // never auto-opened — the operator clicks it themselves. -const figmaTokenSettingsURL = "https://www.figma.com/settings" +const figmaTokenSettingsURL = "https://www.figma.com/settings" // #nosec G101 -- public settings URL printed for the operator, not a credential // figmaAPIBase overrides the Figma API base URL in tests ("" = production). var figmaAPIBase = "" diff --git a/internal/engine/design_context.go b/internal/engine/design_context.go index 662b72b..f9a2c89 100644 --- a/internal/engine/design_context.go +++ b/internal/engine/design_context.go @@ -65,7 +65,7 @@ func copyDesignDir(repoDir, worktreePath string) { log.Printf("[figma] copy %s: %v", e.Name(), err) continue } - if err := os.WriteFile(filepath.Join(dst, e.Name()), data, 0o600); err != nil { + if err := os.WriteFile(filepath.Join(dst, e.Name()), data, 0o600); err != nil { // #nosec G703 -- e.Name() is an os.ReadDir base name from our own design dir; it cannot contain path separators log.Printf("[figma] write %s to worktree: %v", e.Name(), err) } } diff --git a/internal/figma/token.go b/internal/figma/token.go index fbb8064..aca6812 100644 --- a/internal/figma/token.go +++ b/internal/figma/token.go @@ -9,7 +9,7 @@ import ( // TokenEnvVar is the environment variable checked first for a Figma // personal access token. -const TokenEnvVar = "FIGMA_TOKEN" +const TokenEnvVar = "FIGMA_TOKEN" // #nosec G101 -- env var NAME, not a credential value // tokenFileName under the vxd state dir (mode 0o600). const tokenFileName = "figma.token" diff --git a/internal/memory/server.go b/internal/memory/server.go index ddd2866..0a5d74f 100644 --- a/internal/memory/server.go +++ b/internal/memory/server.go @@ -90,7 +90,8 @@ func (s *Server) Start(ctx context.Context) error { BootstrapNonce: nonce, })(s.Handler()) - s.httpServer = &http.Server{Handler: handler} + // ReadHeaderTimeout bounds header dribble (Slowloris defence, gosec G112). + s.httpServer = &http.Server{Handler: handler, ReadHeaderTimeout: 10 * time.Second} url := fmt.Sprintf("http://%s", addr) browserURL := fmt.Sprintf("%s/?%s=%s", url, web.NonceQueryParam, nonce) diff --git a/internal/web/server.go b/internal/web/server.go index 02de176..a381b2a 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -135,7 +135,10 @@ func (s *Server) Start(ctx context.Context) error { handler := authMw(mux) s.rotator = rotator - s.httpServer = &http.Server{Handler: handler} + // ReadHeaderTimeout bounds how long a client may dribble request headers + // (Slowloris defence, gosec G112). 10s is generous for a localhost/LAN + // dashboard while still shedding stuck connections. + s.httpServer = &http.Server{Handler: handler, ReadHeaderTimeout: 10 * time.Second} // Pidfile + bootstrap-file: written BEFORE Serve starts so any caller // that probed /health and got 200 is guaranteed to find the artifacts