fix(ci): allow modernc.org/libc NOASSERTION license in dependency review #956
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security Scanning | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main ] | |
| schedule: | |
| # Run weekly on Sundays at midnight UTC | |
| - cron: '0 0 * * 0' | |
| workflow_dispatch: # Allow manual trigger | |
| permissions: | |
| contents: read | |
| security-events: write | |
| actions: read | |
| env: | |
| GOSEC_SEVERITY: medium | |
| GOSEC_CONFIDENCE: medium | |
| jobs: | |
| gosec: | |
| name: GoSec Security Scanner | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.26' # Match project requirements in go.mod | |
| cache: true | |
| - name: Run GoSec Security Scanner | |
| uses: securego/gosec@v2.21.4 | |
| continue-on-error: true # Don't fail immediately - let validation step decide | |
| with: | |
| # Full recursive scan - severity and confidence levels configurable via env vars | |
| args: '-fmt sarif -out gosec-results.sarif -severity ${{ env.GOSEC_SEVERITY }} -confidence ${{ env.GOSEC_CONFIDENCE }} -exclude=G115 ./...' | |
| - name: Upload GoSec SARIF file | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: gosec-results.sarif | |
| category: gosec | |
| - name: Check GoSec results | |
| if: always() # Always run validation even if scanner step failed | |
| run: | | |
| # Fail the build if high or critical vulnerabilities are found | |
| # Check if SARIF file exists and has results | |
| if [ ! -f gosec-results.sarif ]; then | |
| echo "❌ GoSec SARIF file not found!" | |
| exit 1 | |
| fi | |
| # Check if file has any error-level results using jq | |
| # We use jq to filter, then check if output is non-empty with grep -q . | |
| # This handles the case where jq returns empty output (no vulnerabilities) | |
| if jq -r '.runs[]?.results[]? | select(.level == "error")' gosec-results.sarif 2>/dev/null | grep -q .; then | |
| echo "❌ High or critical security vulnerabilities found!" | |
| jq -r '.runs[]?.results[]? | select(.level == "error") | " - \(.ruleId): \(.message.text)"' gosec-results.sarif || true | |
| exit 1 | |
| else | |
| echo "✅ No high or critical security vulnerabilities found" | |
| fi | |
| trivy-repo: | |
| name: Trivy Repository Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy vulnerability scanner in repo mode | |
| uses: aquasecurity/trivy-action@v0.35.0 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-repo-results.sarif' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| exit-code: '0' # Don't fail on SARIF generation to ensure upload completes | |
| - name: Upload Trivy SARIF to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-repo-results.sarif' | |
| category: trivy-repo | |
| - name: Check Trivy results for critical vulnerabilities | |
| run: | | |
| # Fail the build if high or critical vulnerabilities are found | |
| if [ ! -f trivy-repo-results.sarif ]; then | |
| echo "❌ Trivy SARIF file not found!" | |
| exit 1 | |
| fi | |
| # Check if file has any error or warning level results | |
| # We use jq to filter, then check if output is non-empty with grep -q . | |
| if jq -r '.runs[]?.results[]? | select(.level == "error" or .level == "warning")' trivy-repo-results.sarif 2>/dev/null | grep -q .; then | |
| echo "❌ High or critical vulnerabilities found in repository scan!" | |
| jq -r '.runs[]?.results[]? | select(.level == "error" or .level == "warning") | " - \(.ruleId): \(.message.text)"' trivy-repo-results.sarif || true | |
| exit 1 | |
| else | |
| echo "✅ No high or critical vulnerabilities found" | |
| fi | |
| trivy-config: | |
| name: Trivy Config Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy configuration scanner | |
| uses: aquasecurity/trivy-action@v0.35.0 | |
| with: | |
| scan-type: 'config' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-config-results.sarif' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| exit-code: '0' # Don't fail on SARIF generation to ensure upload completes | |
| - name: Upload Trivy config SARIF | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-config-results.sarif' | |
| category: trivy-config | |
| - name: Check Trivy config results for critical issues | |
| run: | | |
| # Fail the build if high or critical configuration issues are found | |
| if [ ! -f trivy-config-results.sarif ]; then | |
| echo "❌ Trivy config SARIF file not found!" | |
| exit 1 | |
| fi | |
| # Check if file has any error or warning level results | |
| # We use jq to filter, then check if output is non-empty with grep -q . | |
| if jq -r '.runs[]?.results[]? | select(.level == "error" or .level == "warning")' trivy-config-results.sarif 2>/dev/null | grep -q .; then | |
| echo "❌ High or critical configuration issues found!" | |
| jq -r '.runs[]?.results[]? | select(.level == "error" or .level == "warning") | " - \(.ruleId): \(.message.text)"' trivy-config-results.sarif || true | |
| exit 1 | |
| else | |
| echo "✅ No high or critical configuration issues found" | |
| fi | |
| dependency-review: | |
| name: Dependency Review | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@v4 | |
| with: | |
| fail-on-severity: high | |
| # GHSA-x744-4wpc-v9h2: docker/docker AuthZ plugin bypass with oversized | |
| # request bodies. Transitive dep via testcontainers-go (test-only). | |
| # No fixed version available upstream as of 2026-03-29. | |
| allow-ghsas: GHSA-x744-4wpc-v9h2 | |
| # Include both the compound SPDX expression and individual components | |
| # to handle golang.org/x packages which report as compound license | |
| # modernc.org/libc is BSD-3-Clause but GitHub reports NOASSERTION | |
| # due to license detection failure on the modernc.org packages. | |
| allow-licenses: >- | |
| MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, | |
| BlueOak-1.0.0, OFL-1.1, CC-BY-4.0, MPL-2.0, 0BSD, | |
| LicenseRef-scancode-google-patent-license-golang, | |
| BSD-3-Clause AND LicenseRef-scancode-google-patent-license-golang, | |
| LicenseRef-bad-fsl-1.1-mit, | |
| 0BSD AND ISC AND MIT, | |
| LicenseRef-github-NOASSERTION | |
| govulncheck: | |
| name: Go Vulnerability Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.26' # Match project requirements in go.mod | |
| cache: true | |
| - name: Install govulncheck | |
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | |
| - name: Run govulncheck | |
| run: | | |
| # Run govulncheck and capture output | |
| set +e | |
| OUTPUT=$(govulncheck -show verbose ./... 2>&1) | |
| EXIT_CODE=$? | |
| set -e | |
| echo "$OUTPUT" | |
| echo "" | |
| if [ $EXIT_CODE -eq 0 ]; then | |
| echo "✅ No known vulnerabilities found in dependencies" | |
| exit 0 | |
| elif [ $EXIT_CODE -eq 1 ]; then | |
| echo "❌ Error running govulncheck!" | |
| exit 1 | |
| fi | |
| # Exit code 3 = vulnerabilities found | |
| # Check if any are from third-party (non-stdlib) packages | |
| # Stdlib vulns are inherent to the Go version and can't be fixed | |
| # by dependency updates — only report those as informational. | |
| # | |
| # govulncheck output uses "Module: stdlib" for standard library vulns | |
| # and "Module: <module-path>" for third-party vulns. | |
| # We also check "Found in:" lines — stdlib shows package@goversion | |
| # (e.g., net/url@go1.21.13) while third-party shows module paths. | |
| # | |
| # Strategy: extract all Module lines, filter out stdlib, check remainder | |
| MODULES=$(echo "$OUTPUT" | grep -E "^\s*Module:" | sort -u || true) | |
| THIRD_PARTY_MODULES=$(echo "$MODULES" | grep -v "stdlib" || true) | |
| if [ -n "$THIRD_PARTY_MODULES" ]; then | |
| echo "❌ Vulnerabilities found in third-party dependencies!" | |
| echo "$THIRD_PARTY_MODULES" | |
| echo "Please review the vulnerability report above and update affected dependencies." | |
| exit 1 | |
| else | |
| echo "⚠️ Only standard library vulnerabilities found (inherent to Go version)." | |
| echo "These cannot be fixed by dependency updates — upgrade Go version to resolve." | |
| echo "✅ No third-party dependency vulnerabilities — passing." | |
| fi | |
| security-summary: | |
| name: Security Scan Summary | |
| runs-on: ubuntu-latest | |
| needs: [gosec, trivy-repo, trivy-config, govulncheck] | |
| if: always() | |
| steps: | |
| - name: Check job status | |
| run: | | |
| echo "### Security Scan Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Scanner | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|---------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| GoSec | ${{ needs.gosec.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Trivy Repo | ${{ needs.trivy-repo.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Trivy Config | ${{ needs.trivy-config.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| GovulnCheck | ${{ needs.govulncheck.result }} |" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.gosec.result }}" != "success" ] || \ | |
| [ "${{ needs.trivy-repo.result }}" != "success" ] || \ | |
| [ "${{ needs.trivy-config.result }}" != "success" ] || \ | |
| [ "${{ needs.govulncheck.result }}" != "success" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "⚠️ **Some security checks failed. Please review the results above.**" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| else | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ **All security checks passed successfully!**" >> $GITHUB_STEP_SUMMARY | |
| fi |