From 7da18d3a8ce37b302a11e6aa8782c6560c74ede5 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Fri, 9 Jan 2026 13:27:06 +0100 Subject: [PATCH] Replace unavailable gosec with comprehensive security scanning - Replace gosec with govulncheck (official Go vulnerability scanner) - Add dedicated security.yml workflow with multiple tools: - govulncheck: Official Go team vulnerability scanner - Nancy: Sonatype dependency vulnerability scanner - Staticcheck: Go static analysis with security checks - Semgrep: Multi-language security scanner - CodeQL: GitHub semantic security analysis - Dependency Review: Automated dependency vulnerability checking - Update golangci-lint config to temporarily disable gosec - Add CodeQL configuration for enhanced Go security analysis - Separate fast CI checks from comprehensive security scanning - Schedule daily security scans at 2 AM UTC - Integrate with GitHub Security tab via SARIF reports --- .github/codeql-config.yml | 74 ++++++++++++++ .github/workflows/ci.yml | 20 ++-- .github/workflows/security.yml | 172 +++++++++++++++++++++++++++++++++ .golangci.yml | 111 ++++++++++----------- 4 files changed, 312 insertions(+), 65 deletions(-) create mode 100644 .github/codeql-config.yml create mode 100644 .github/workflows/security.yml diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml new file mode 100644 index 0000000..0ca3b2a --- /dev/null +++ b/.github/codeql-config.yml @@ -0,0 +1,74 @@ +# CodeQL configuration for enhanced security analysis +# See: https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/creating-codeql-query-suites + +name: "Go Security Analysis" + +disable-default-queries: false + +queries: + # Include default security queries + - uses: security-extended + - uses: security-and-quality + + # Additional Go-specific security queries + - name: go-security-extra + uses: + - go/bad-redirect-check + - go/clear-text-logging + - go/incorrect-integer-conversion + - go/log-injection + - go/missing-regexp-anchor + - go/path-injection + - go/request-forgery + - go/sensitive-package-import + - go/sql-injection + - go/uncontrolled-allocation-size + - go/unsafe-quoting + - go/useless-regexp-character-escape + - go/zip-slip + +# Configure paths to exclude from analysis +paths-ignore: + - "**/*.pb.go" # Generated protobuf files + - "**/*_gen.go" # Generated code + - "**/vendor/**" # Vendor dependencies + - "**/build/**" # Build artifacts + - "**/scripts/**" # Build scripts + - "**/*_test.go" # Test files (optional - remove if you want to analyze tests) + +# Configure paths to include (if not specified, all Go files are included) +paths: + - "cmd/**/*.go" + - "pkg/**/*.go" + - "*.go" + +# Query filters to reduce noise +query-filters: + - exclude: + id: go/unused-variable + reason: "Can be noisy in development" + - exclude: + id: go/hardcoded-credentials + reason: "Will be handled by separate secret scanning" + +# Configuration for specific query packs +packs: + # Use the official CodeQL Go queries + - codeql/go-queries + + # Additional community query packs for enhanced security + - codeql/go-queries@~0.0.0 # Latest version + +# Custom configuration for specific queries +query-config: + go/path-injection: + # Configure severity levels + severity: "error" + go/sql-injection: + severity: "error" + go/request-forgery: + severity: "warning" + go/log-injection: + severity: "warning" + go/clear-text-logging: + severity: "note" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e5b5ff..cf42b84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: path: soundtouch-cli-* security: - name: Security Scan + name: Basic Security Check runs-on: ubuntu-latest steps: @@ -118,16 +118,16 @@ jobs: with: go-version-file: "go.mod" - - name: Install Gosec - run: go install github.com/securecodewarrior/gosec/v2/cmd/gosec@latest - - - name: Run Gosec Security Scanner - run: gosec ./... - - - name: Run Nancy vulnerability scanner + - name: Run basic vulnerability check run: | - go install github.com/sonatypecommunity/nancy@latest - go list -json -deps ./... | nancy sleuth + go install golang.org/x/vuln/cmd/govulncheck@latest + govulncheck ./... + + - name: Security scan reminder + run: | + echo "ℹ️ This is a basic security check for CI speed." + echo "For comprehensive security scanning, see the Security workflow:" + echo "https://github.com/${{ github.repository }}/actions/workflows/security.yml" docs: name: Documentation Check diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..50672ef --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,172 @@ +name: Security + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + # Run security scans daily at 2 AM UTC + - cron: '0 2 * * *' + workflow_dispatch: + +jobs: + vulnerability-scan: + name: Vulnerability Scan + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: "go.mod" + + - name: Install security scanning tools + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + go install github.com/sonatypecommunity/nancy@latest + + - name: Run govulncheck (Official Go vulnerability scanner) + run: | + echo "::group::Running govulncheck" + govulncheck ./... + echo "::endgroup::" + + - name: Run Nancy vulnerability scanner + run: | + echo "::group::Running Nancy dependency scanner" + go list -json -deps ./... | nancy sleuth + echo "::endgroup::" + + - name: Upload vulnerability scan results + if: failure() + uses: actions/upload-artifact@v6 + with: + name: vulnerability-scan-results + path: | + vulnerability-report.json + nancy-report.json + + static-analysis: + name: Static Security Analysis + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: "go.mod" + + - name: Install static analysis tools + run: | + go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck security analysis + run: | + echo "::group::Running staticcheck" + staticcheck ./... + echo "::endgroup::" + + - name: Run Semgrep security analysis + uses: semgrep/semgrep-action@v1 + with: + config: >- + p/security-audit + p/secrets + p/golang + generateSarif: "1" + continue-on-error: true + + - name: Upload Semgrep SARIF results + if: always() + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: semgrep.sarif + continue-on-error: true + + codeql-analysis: + name: CodeQL Analysis + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: go + config-file: ./.github/codeql-config.yml + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:go" + + dependency-review: + name: Dependency Review + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Dependency Review + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: moderate + allow-ghsas: GHSA-xxxx-xxxx-xxxx # Add specific allowlisted advisories if needed + deny-licenses: GPL-2.0, LGPL-2.0 # Add licenses to deny if needed + + security-summary: + name: Security Summary + runs-on: ubuntu-latest + needs: [vulnerability-scan, static-analysis, codeql-analysis] + if: always() + + steps: + - name: Security scan summary + run: | + echo "## Security Scan Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [[ "${{ needs.vulnerability-scan.result }}" == "success" ]]; then + echo "✅ **Vulnerability Scan**: PASSED" >> $GITHUB_STEP_SUMMARY + else + echo "❌ **Vulnerability Scan**: FAILED" >> $GITHUB_STEP_SUMMARY + fi + + if [[ "${{ needs.static-analysis.result }}" == "success" ]]; then + echo "✅ **Static Analysis**: PASSED" >> $GITHUB_STEP_SUMMARY + else + echo "❌ **Static Analysis**: FAILED" >> $GITHUB_STEP_SUMMARY + fi + + if [[ "${{ needs.codeql-analysis.result }}" == "success" ]]; then + echo "✅ **CodeQL Analysis**: PASSED" >> $GITHUB_STEP_SUMMARY + else + echo "❌ **CodeQL Analysis**: FAILED" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "For detailed results, check the individual job logs above." >> $GITHUB_STEP_SUMMARY + + - name: Fail on security issues + if: needs.vulnerability-scan.result == 'failure' || needs.static-analysis.result == 'failure' || needs.codeql-analysis.result == 'failure' + run: | + echo "Security scan detected issues. Please review the results above." + exit 1 diff --git a/.golangci.yml b/.golangci.yml index 0a5be25..6be506e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,49 +23,49 @@ output: linters: enable: # Default linters - - errcheck # Check for unchecked errors - - gosimple # Simplify code - - govet # Vet examines Go source code - - ineffassign # Detect ineffectual assignments - - staticcheck # Go static analysis - - typecheck # Parse and type-check Go code - - unused # Check for unused constants, variables, functions and types + - errcheck # Check for unchecked errors + - gosimple # Simplify code + - govet # Vet examines Go source code + - ineffassign # Detect ineffectual assignments + - staticcheck # Go static analysis + - typecheck # Parse and type-check Go code + - unused # Check for unused constants, variables, functions and types # Additional useful linters for production code - - gofmt # Check whether code was gofmt-ed - - goimports # Check import sorting - - misspell # Find commonly misspelled English words - - unconvert # Remove unnecessary type conversions - - unparam # Report unused function parameters - - gocyclo # Compute cyclomatic complexities - - gocritic # Most opinionated Go source code linter - - gosec # Inspect source code for security problems - - exportloopref # Check for pointers to enclosing loop variables - - nolintlint # Reports ill-formed or insufficient nolint directives - - revive # Fast, configurable, extensible, flexible, and beautiful linter - - stylecheck # Stylecheck is a replacement for golint - - whitespace # Tool for detection of leading and trailing whitespace - - wsl # Whitespace Linter - Forces you to use empty lines - - predeclared # Find code that shadows one of Go's predeclared identifiers - - thelper # Detect golang test helpers without t.Helper() call - - tparallel # Detect inappropriate usage of t.Parallel() method in tests - - bodyclose # Check whether HTTP response body is closed successfully - - nilerr # Find the code that returns nil even if it checks that the error is not nil - - nilnil # Check that there is no simultaneous return of nil error and an invalid value - - errchkjson # Check types passed to the json encoding functions - - errorlint # Find code that will cause problems with the error wrapping scheme - - contextcheck # Check the function whether use a non-inherited context + - gofmt # Check whether code was gofmt-ed + - goimports # Check import sorting + - misspell # Find commonly misspelled English words + - unconvert # Remove unnecessary type conversions + - unparam # Report unused function parameters + - gocyclo # Compute cyclomatic complexities + - gocritic # Most opinionated Go source code linter + # - gosec # Inspect source code for security problems (temporarily disabled - use govulncheck instead) + - exportloopref # Check for pointers to enclosing loop variables + - nolintlint # Reports ill-formed or insufficient nolint directives + - revive # Fast, configurable, extensible, flexible, and beautiful linter + - stylecheck # Stylecheck is a replacement for golint + - whitespace # Tool for detection of leading and trailing whitespace + - wsl # Whitespace Linter - Forces you to use empty lines + - predeclared # Find code that shadows one of Go's predeclared identifiers + - thelper # Detect golang test helpers without t.Helper() call + - tparallel # Detect inappropriate usage of t.Parallel() method in tests + - bodyclose # Check whether HTTP response body is closed successfully + - nilerr # Find the code that returns nil even if it checks that the error is not nil + - nilnil # Check that there is no simultaneous return of nil error and an invalid value + - errchkjson # Check types passed to the json encoding functions + - errorlint # Find code that will cause problems with the error wrapping scheme + - contextcheck # Check the function whether use a non-inherited context disable: - - gocognit # Can be too strict for some cases - - funlen # Function length can vary based on complexity - - lll # Line length limit - we'll handle this with gofmt - - gomnd # Magic numbers detector - can be overly aggressive - - exhaustive # Can be too strict for enums - - testpackage # Not always necessary to put tests in separate package - - wrapcheck # Error wrapping can be context-dependent - - nlreturn # Can conflict with other formatting preferences - - gofumpt # Use standard gofmt instead + - gocognit # Can be too strict for some cases + - funlen # Function length can vary based on complexity + - lll # Line length limit - we'll handle this with gofmt + - gomnd # Magic numbers detector - can be overly aggressive + - exhaustive # Can be too strict for enums + - testpackage # Not always necessary to put tests in separate package + - wrapcheck # Error wrapping can be context-dependent + - nlreturn # Can conflict with other formatting preferences + - gofumpt # Use standard gofmt instead linters-settings: errcheck: @@ -80,7 +80,7 @@ linters-settings: check-shadowing: true enable-all: true disable: - - fieldalignment # Can be overly aggressive + - fieldalignment # Can be overly aggressive gocyclo: min-complexity: 15 @@ -132,18 +132,19 @@ linters-settings: - weakCond - yodaStyleExpr - gosec: - excludes: - - G104 # Audit errors not checked - handled by errcheck - config: - G301: "0755" # Poor file permissions - G302: "0755" # Poor file permissions - G306: "0755" # Poor file permissions + # gosec: + # excludes: + # - G104 # Audit errors not checked - handled by errcheck + # config: + # G301: "0755" # Poor file permissions + # G302: "0755" # Poor file permissions + # G306: "0755" # Poor file permissions revive: rules: - name: var-naming - arguments: [["ID", "URL", "HTTP", "JSON", "XML", "API", "UUID", "SQL"], []] + arguments: + [["ID", "URL", "HTTP", "JSON", "XML", "API", "UUID", "SQL"], []] - name: exported arguments: [true] - name: blank-imports @@ -170,7 +171,7 @@ linters-settings: - name: waitgroup-by-value stylecheck: - checks: ["all", "-ST1003"] # Disable ST1003 (should not use underscores in Go names) + checks: ["all", "-ST1003"] # Disable ST1003 (should not use underscores in Go names) whitespace: multi-if: false @@ -188,10 +189,10 @@ issues: # Exclude some linters from running on tests files - path: _test\.go linters: - - gosec # Security issues less critical in tests - - gocritic # Can be overly strict for test code - - wsl # Whitespace less critical in tests - - gocyclo # Complexity less critical in tests + # - gosec # Security issues less critical in tests (currently disabled) + - gocritic # Can be overly strict for test code + - wsl # Whitespace less critical in tests + - gocyclo # Complexity less critical in tests # Exclude specific rules for generated files - path: ".*\\.pb\\.go$" @@ -201,12 +202,12 @@ issues: # Exclude some staticcheck messages - linters: - staticcheck - text: "SA9003:" # Empty branch + text: "SA9003:" # Empty branch # Exclude some gosimple messages - linters: - gosimple - text: "S1002:" # Omit comparison with boolean constant + text: "S1002:" # Omit comparison with boolean constant # Allow main functions to not check errors in examples - path: cmd/.*\.go