diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index f7abd265365..ec7995c6b16 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -26,11 +26,10 @@ jobs: - name: Run Gosec run: | - go install github.com/securego/gosec/v2/cmd/gosec@v2.28.0 # Keep only globally noisy rules here. # G602 (slice bounds check) is excluded globally due persistent false positives. # Use inline '#nosec Gxxx -- justification' suppressions for specific findings. - gosec -fmt sarif -out gosec-results.sarif -stdout -exclude-generated -track-suppressions \ + go tool gosec -fmt sarif -out gosec-results.sarif -stdout -exclude-generated -track-suppressions \ -nosec-require-rules -nosec-require-justification \ -exclude=G602 \ ./... @@ -56,7 +55,7 @@ jobs: cache: true - name: Run govulncheck - run: go run -mod=readonly golang.org/x/vuln/cmd/govulncheck -format sarif ./... > govulncheck-results.sarif; ret=$?; [ $ret -eq 0 ] || [ $ret -eq 3 ] + run: go tool govulncheck -format sarif ./... > govulncheck-results.sarif; ret=$?; [ $ret -eq 0 ] || [ $ret -eq 3 ] - name: Upload govulncheck SARIF uses: github/codeql-action/upload-sarif@4248455a6f2335bc3b7a8a62932f000050ec8f13 # v3 diff --git a/.golangci.yml b/.golangci.yml index 070bd3e3e4f..4a2a3c561ec 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -68,33 +68,6 @@ linters-settings: - deprecatedComment # Allow existing deprecated comment format - commentFormatting # Allow commented out code - badCall # filepath.Join with 1 arg is acceptable - gosec: - # NOTE: gosec is disabled in golangci-lint due to configuration bugs in v2. - # These exclusions apply only if gosec is re-enabled in golangci-lint. - # Standalone gosec execution uses Makefile/.github/workflows/security-scan.yml. - # - G101: Potential hardcoded credentials (often false positives) - # - G115: Integer overflow conversion (acceptable in most cases) - # - G204: Subprocess with variable args - all exec.Command calls use separate args - # (not shell execution), making shell injection impossible. Specific high-risk - # cases (user-controlled command names) are mitigated by exec.LookPath validation - # and documented with inline #nosec G204 annotations. - # - G602: Slice bounds check (handled by runtime) - # - G301: Directory permissions 0755 (acceptable for non-sensitive dirs) - # - G302: File permissions 0755 (acceptable for chmod operations) - # - G304: File inclusion via variable (validated file paths) - # - G306: WriteFile permissions 0644 (acceptable for non-sensitive files) - exclude: - - G101 - - G115 - - G204 - - G602 - - G301 - - G302 - - G304 - - G306 - config: - G204: "0644" # Allow common file permissions in tests - G306: "0644" # Allow common file permissions testifylint: enable-all: true @@ -102,8 +75,6 @@ issues: exclude-generated: lax exclude-dirs-use-default: false exclude-use-default: false - # NOTE: The issues.exclude field does not work properly in golangci-lint v2 - # Exclusions for gosec are applied when running gosec directly via 'make security-gosec' exclude-rules: - linters: - staticcheck @@ -113,97 +84,6 @@ issues: - staticcheck text: "ST1005: error strings should not end with punctuation or newlines" # Allow multiline user-facing error messages with formatting path: pkg/workflow/dispatch_workflow_validation\.go - - linters: - - gosec - text: "^G304:" # Ignore "file inclusion via variable" - validated file paths - - linters: - - gosec - text: "^G104:" # Ignore "errors unhandled" - intentional in tests - path: _test\.go - - linters: - - gosec - text: "^G204:" # Allow docker commands in actionlint - path: pkg/cli/actionlint\.go - - linters: - - gosec - text: "^G204:" # Allow git commands in remote_fetch - path: pkg/parser/remote_fetch\.go - - linters: - - gosec - text: "^G404:" # Allow math/rand for non-crypto purposes - path: pkg/cli/(add_command|update_git)\.go - - linters: - - gosec - text: "^G306:" # Allow 0644 permissions in test files - path: _test\.go - - linters: - - gosec - text: "^G305:" # Allow file path operations in logs_download - path: pkg/cli/logs_download\.go - - linters: - - gosec - text: "^G110:" # Allow decompression in logs_download - path: pkg/cli/logs_download\.go - - linters: - - gosec - text: "^G204:" # Allow git commands in download_workflow - path: pkg/cli/download_workflow\.go - - linters: - - gosec - text: "^G204:" # Allow exec.Command with config in mcp_inspect - path: pkg/cli/mcp_inspect\.go - - linters: - - gosec - text: "^G204:" # Allow exec.Command with config in mcp_inspect_mcp - path: pkg/cli/mcp_inspect_mcp\.go - - linters: - - gosec - text: "^G306:" # 0755 is correct permission for executable script - path: pkg/cli/mcp_inspect\.go - - linters: - - gosec - text: "^G204:" # Allow docker commands in poutine - path: pkg/cli/poutine\.go - - linters: - - gosec - text: "^G204:" # Allow node command in tests - path: pkg/workflow/js_comments_test\.go - - linters: - - gosec - text: "^G204:" # Allow npx command in integration tests - path: pkg/workflow/playwright_mcp_integration_test\.go - - linters: - - gosec - text: "^G204:" # Allow exec of binary in status tests - path: pkg/cli/status_command_test\.go - - linters: - - gosec - text: "^G204:" # Allow docker commands in zizmor - path: pkg/cli/zizmor\.go - - linters: - - gosec - text: "^G304:" # Allow file inclusion in parser for frontmatter/includes - path: pkg/parser/(frontmatter_content|include_expander|include_processor)\.go - - linters: - - gosec - text: "^G301:" # Allow directory permissions in parser cache - path: pkg/parser/(import_cache|frontmatter_includes_test)\.go - - linters: - - gosec - text: "^G306:" # Allow file write permissions in parser cache - path: pkg/parser/import_cache\.go - - linters: - - gosec - text: "^G301:" # Allow directory permissions in testutil - path: pkg/testutil/tempdir\.go - - linters: - - gosec - text: "^G101:" # Allow string literals in safe outputs that look like env var names - path: pkg/workflow/compiler_safe_outputs_core\.go - - linters: - - gosec - text: "^G204:" # Allow mcp inspect commands with docker - path: pkg/cli/mcp_inspect_mcp\.go - linters: - unconvert path: _test\.go # Allow explicit conversions in tests for clarity diff --git a/Makefile b/Makefile index 29c610ecb73..e962bbd1c13 100644 --- a/Makefile +++ b/Makefile @@ -224,12 +224,10 @@ security-scan: security-gosec security-govulncheck .PHONY: security-gosec security-gosec: @echo "Running gosec security scanner..." - @go install github.com/securego/gosec/v2/cmd/gosec@v2.28.0 @# Keep only globally noisy rules here. @# G602 (slice bounds check) is excluded globally due persistent false positives. @# Use inline '#nosec Gxxx -- justification' suppressions for specific findings. - @GOPATH=$$(go env GOPATH); \ - PATH="$$GOPATH/bin:$$PATH" gosec -fmt=json -out=gosec-report.json -stdout -exclude-generated -track-suppressions \ + @go tool gosec -fmt=json -out=gosec-report.json -stdout -exclude-generated -track-suppressions \ -nosec-require-rules -nosec-require-justification \ -exclude=G602 \ ./... @@ -238,13 +236,13 @@ security-gosec: .PHONY: security-govulncheck security-govulncheck: @echo "Running govulncheck..." - go run golang.org/x/vuln/cmd/govulncheck ./... + @go tool govulncheck ./... @echo "✓ Govulncheck complete" .PHONY: security-govulncheck-sarif security-govulncheck-sarif: @echo "Running govulncheck (SARIF output)..." - go run -mod=readonly golang.org/x/vuln/cmd/govulncheck -format sarif ./... > govulncheck-results.sarif; ret=$$?; [ $$ret -eq 0 ] || [ $$ret -eq 3 ] + @go tool govulncheck -format sarif ./... > govulncheck-results.sarif; ret=$$?; [ $$ret -eq 0 ] || [ $$ret -eq 3 ] @echo "✓ Govulncheck complete (results in govulncheck-results.sarif)" # Test JavaScript files @@ -634,10 +632,11 @@ check-node-version: echo "✓ Node.js version check passed ($$NODE_VERSION)" .PHONY: tools -tools: ## Install build-time tools from tools.go +tools: ## Install build-time tools declared in go.mod tool directives @echo "Installing build tools..." - @go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12 - @go install github.com/securego/gosec/v2/cmd/gosec@v2.28.0 + @go install github.com/rhysd/actionlint/cmd/actionlint + @go install github.com/securego/gosec/v2/cmd/gosec + @go install golang.org/x/vuln/cmd/govulncheck @go install golang.org/x/tools/gopls@v0.21.1 @echo "✓ Tools installed successfully" @@ -1266,7 +1265,7 @@ help: @echo " actions-validate - Validate action.yml files" @echo " actions-clean - Clean action build artifacts" @echo " generate-action-metadata - Generate action.yml and README.md from JavaScript modules" - @echo " tools - Install build-time tools from tools.go" + @echo " tools - Install build-time tools declared in go.mod tool directives" @echo " license-check - Check dependency licenses for compliance" @echo " license-report - Generate CSV license report" @echo " deps - Install dependencies" diff --git a/go.mod b/go.mod index 7b5081531ea..09ec91df310 100644 --- a/go.mod +++ b/go.mod @@ -16,9 +16,7 @@ require ( github.com/goccy/go-yaml v1.19.2 github.com/google/jsonschema-go v0.4.3 github.com/modelcontextprotocol/go-sdk v1.6.1 - github.com/rhysd/actionlint v1.7.12 github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 - github.com/securego/gosec/v2 v2.28.0 github.com/sourcegraph/conc v0.3.0 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 @@ -29,7 +27,6 @@ require ( golang.org/x/sync v0.22.0 golang.org/x/term v0.45.0 golang.org/x/tools v0.48.0 - golang.org/x/vuln v1.6.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -86,8 +83,10 @@ require ( github.com/openai/openai-go/v3 v3.42.0 // indirect github.com/pb33f/ordered-map/v2 v2.3.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rhysd/actionlint v1.7.12 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/securego/gosec/v2 v2.28.0 // indirect github.com/segmentio/asm v1.1.3 // indirect github.com/segmentio/encoding v0.5.4 // indirect github.com/standard-webhooks/standard-webhooks/libraries v0.0.1 // indirect @@ -112,9 +111,16 @@ require ( golang.org/x/sys v0.47.0 // indirect golang.org/x/telemetry v0.0.0-20260708182218-49f421fb7959 // indirect golang.org/x/text v0.40.0 // indirect + golang.org/x/vuln v1.6.0 // indirect google.golang.org/api v0.288.0 // indirect google.golang.org/genai v1.63.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800 // indirect google.golang.org/grpc v1.82.1 // indirect google.golang.org/protobuf v1.36.11 // indirect ) + +tool ( + github.com/rhysd/actionlint/cmd/actionlint + github.com/securego/gosec/v2/cmd/gosec + golang.org/x/vuln/cmd/govulncheck +) diff --git a/tools.go b/tools.go deleted file mode 100644 index 634c64d65cd..00000000000 --- a/tools.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build tools - -// Package tools tracks build-time tool dependencies. -// Import tools here with blank imports to include them in go.mod. -// This ensures consistent tool versions across development and CI. -// Note: golangci-lint is installed via binary distribution to avoid GPL dependencies -package tools - -import ( - _ "github.com/rhysd/actionlint/cmd/actionlint" - _ "github.com/securego/gosec/v2/cmd/gosec" - _ "golang.org/x/vuln/cmd/govulncheck" -)