diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a5c98a..6c44530 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,8 +69,8 @@ jobs: bash scripts/check_repo_hygiene.sh git config core.hooksPath .githooks go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.1 - go install github.com/securego/gosec/v2/cmd/gosec@v2.22.0 - go install golang.org/x/vuln/cmd/govulncheck@latest + go install github.com/securego/gosec/v2/cmd/gosec@v2.23.0 + go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 go vet ./... golangci-lint run ./... gosec ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 855e250..df980f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: - "v*" env: - GORELEASER_VERSION: v2.7.0 + GORELEASER_VERSION: v2.13.3 SYFT_VERSION: v1.32.0 GRYPE_VERSION: v0.99.1 COSIGN_VERSION: v2.5.3 diff --git a/Makefile b/Makefile index 148df5f..5b37e61 100644 --- a/Makefile +++ b/Makefile @@ -34,9 +34,9 @@ lint: bash scripts/check_hooks_config.sh $(GO) vet ./... $(GO) run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.1 run ./... - $(GO) run github.com/securego/gosec/v2/cmd/gosec@v2.22.0 ./... + $(GO) run github.com/securego/gosec/v2/cmd/gosec@v2.23.0 ./... $(GO) build -o $(GAIT_BINARY) ./cmd/gait - $(GO) run golang.org/x/vuln/cmd/govulncheck@latest -mode=binary $(GAIT_BINARY) + $(GO) run golang.org/x/vuln/cmd/govulncheck@v1.1.4 -mode=binary $(GAIT_BINARY) (cd $(SDK_DIR) && uv run --python $(UV_PY) --extra dev ruff check) (cd $(SDK_DIR) && uv run --python $(UV_PY) --extra dev mypy) (cd $(SDK_DIR) && uv run --python $(UV_PY) --extra dev bandit -q -r gait) diff --git a/cmd/gait/mcp.go b/cmd/gait/mcp.go index bc9bd65..7cb74c5 100644 --- a/cmd/gait/mcp.go +++ b/cmd/gait/mcp.go @@ -55,7 +55,7 @@ type mcpProxyEvalOptions struct { LogExportPath string OTelExport string KeyMode string - PrivateKey string + PrivateKey string // #nosec G117 -- field name is explicit config surface, not a hardcoded secret. PrivateKeyEnv string } diff --git a/cmd/gait/mcp_server.go b/cmd/gait/mcp_server.go index 5b74714..c38ea54 100644 --- a/cmd/gait/mcp_server.go +++ b/cmd/gait/mcp_server.go @@ -25,7 +25,7 @@ type mcpServeConfig struct { DefaultAdapter string Profile string AuthMode string - AuthToken string + AuthToken string // #nosec G117 -- field name is explicit config surface, not a hardcoded secret. TraceDir string RunpackDir string PackDir string @@ -44,7 +44,7 @@ type mcpServeConfig struct { LogExportPath string OTelExport string KeyMode string - PrivateKey string + PrivateKey string // #nosec G117 -- field name is explicit config surface, not a hardcoded secret. PrivateKeyEnv string } @@ -535,7 +535,7 @@ func writeMCPServeSSE(writer http.ResponseWriter, status int, payload mcpServeEv } _, _ = writer.Write([]byte("event: evaluate\n")) _, _ = writer.Write([]byte("data: ")) - _, _ = writer.Write(encoded) + _, _ = writer.Write(encoded) // #nosec G705 -- writes JSON payload to SSE stream, not HTML. _, _ = writer.Write([]byte("\n\n")) if flusher, ok := writer.(http.Flusher); ok { flusher.Flush() diff --git a/cmd/gait/migrate.go b/cmd/gait/migrate.go index 8372082..32e6e6b 100644 --- a/cmd/gait/migrate.go +++ b/cmd/gait/migrate.go @@ -131,8 +131,8 @@ func runMigrate(arguments []string) int { } status := "migrated" - oldBytes, oldErr := os.ReadFile(resolvedInput) - newBytes, newErr := os.ReadFile(outputPath) + oldBytes, oldErr := os.ReadFile(resolvedInput) // #nosec G304 -- resolvedInput is canonicalized local path from CLI input. + newBytes, newErr := os.ReadFile(outputPath) // #nosec G304 -- outputPath is a local destination path selected by command. if oldErr == nil && newErr == nil && bytes.Equal(oldBytes, newBytes) { status = "no_change" } diff --git a/core/fsx/fsx.go b/core/fsx/fsx.go index eb2a295..7104936 100644 --- a/core/fsx/fsx.go +++ b/core/fsx/fsx.go @@ -107,6 +107,7 @@ func renameWithValidatedTempPath(tempPath string, path string, goos string) erro } func renameWithWindowsSemantics(tempPath string, path string, goos string) error { + // #nosec G703 -- both paths are validated local/absolute before entering this function. if err := os.Rename(tempPath, path); err != nil { if goos != "windows" { return fmt.Errorf("rename temp file: %w", err) @@ -114,6 +115,7 @@ func renameWithWindowsSemantics(tempPath string, path string, goos string) error if removeErr := os.Remove(path); removeErr != nil && !os.IsNotExist(removeErr) { return fmt.Errorf("remove destination before rename: %w", removeErr) } + // #nosec G703 -- both paths are validated local/absolute before entering this function. if renameErr := os.Rename(tempPath, path); renameErr != nil { return fmt.Errorf("rename temp file after remove: %w", renameErr) } diff --git a/core/projectconfig/config.go b/core/projectconfig/config.go index b723a68..046d07c 100644 --- a/core/projectconfig/config.go +++ b/core/projectconfig/config.go @@ -20,7 +20,7 @@ type GateDefaults struct { Policy string `yaml:"policy"` Profile string `yaml:"profile"` KeyMode string `yaml:"key_mode"` - PrivateKey string `yaml:"private_key"` + PrivateKey string `yaml:"private_key"` // #nosec G117 -- config key name documents expected secret input. PrivateKeyEnv string `yaml:"private_key_env"` ApprovalPublicKey string `yaml:"approval_public_key"` ApprovalPublicKeyEnv string `yaml:"approval_public_key_env"` diff --git a/core/registry/install.go b/core/registry/install.go index 96e0043..8e0e564 100644 --- a/core/registry/install.go +++ b/core/registry/install.go @@ -303,6 +303,7 @@ func fetchRemoteSourceOnce(ctx context.Context, source string, client *http.Clie if err != nil { return nil, fmt.Errorf("build source request: %w", err) } + // #nosec G704 -- source URL is policy-controlled and validated by caller before fetch. response, err := httpClient.Do(request) if err != nil { return nil, err diff --git a/core/regress/init.go b/core/regress/init.go index fce9fa6..5b5f3b5 100644 --- a/core/regress/init.go +++ b/core/regress/init.go @@ -324,10 +324,12 @@ func materializeRunpackSource(sourcePath string) (string, func(), error) { tempPath := tempFile.Name() if _, err := tempFile.Write(extracted); err != nil { _ = tempFile.Close() + // #nosec G703 -- tempPath is created by os.CreateTemp in this function. _ = os.Remove(tempPath) return "", func() {}, fmt.Errorf("materialize source runpack: %w", err) } if err := tempFile.Close(); err != nil { + // #nosec G703 -- tempPath is created by os.CreateTemp in this function. _ = os.Remove(tempPath) return "", func() {}, fmt.Errorf("materialize source runpack: %w", err) } diff --git a/core/ui/runner.go b/core/ui/runner.go index 5095257..48d3a5b 100644 --- a/core/ui/runner.go +++ b/core/ui/runner.go @@ -21,7 +21,7 @@ func defaultRunner(ctx context.Context, workDir string, argv []string) (runResul if len(argv) == 0 { return runResult{}, fmt.Errorf("missing command") } - command := exec.CommandContext(ctx, argv[0], argv[1:]...) // #nosec G204 + command := exec.CommandContext(ctx, argv[0], argv[1:]...) // #nosec G204,G702 command.Dir = strings.TrimSpace(workDir) var stdoutBuf bytes.Buffer var stderrBuf bytes.Buffer diff --git a/go.mod b/go.mod index ac424d8..991afba 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,11 @@ module github.com/Clyra-AI/gait go 1.25.7 require ( - github.com/Clyra-AI/proof v0.1.0 + github.com/Clyra-AI/proof v0.3.0 github.com/goccy/go-yaml v1.19.2 ) require ( github.com/gowebpki/jcs v1.0.1 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/stretchr/testify v1.11.1 // indirect ) diff --git a/go.sum b/go.sum index b4459b2..4625fd2 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/Clyra-AI/proof v0.1.0 h1:TS4M8nUurbMMF4Fdvdnv00fv09MRgAMc8OK6JPTGlXY= -github.com/Clyra-AI/proof v0.1.0/go.mod h1:EDff6buidj222E+EYyqQXXj1rtPgSFlYOxl2JFfWKFs= +github.com/Clyra-AI/proof v0.3.0 h1:3AjRK3YqGuzWZCzhu6isXKr/EGNoOvo/kkkM4JFxNqI= +github.com/Clyra-AI/proof v0.3.0/go.mod h1:EDff6buidj222E+EYyqQXXj1rtPgSFlYOxl2JFfWKFs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -13,8 +13,8 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6Ng github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=