Security Scan #177
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 Scan | |
| on: | |
| schedule: | |
| - cron: '0 2 * * *' # Daily at 2 AM UTC | |
| workflow_dispatch: | |
| jobs: | |
| secrets: | |
| name: Secret Detection | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: cachix/install-nix-action@v25 | |
| with: | |
| nix_path: nixpkgs=channel:nixos-unstable | |
| - name: Gitleaks scan | |
| id: gitleaks | |
| continue-on-error: true | |
| run: | | |
| nix shell nixpkgs#gitleaks --command \ | |
| gitleaks detect --source . --report-path gitleaks-report.json --verbose | |
| - name: Upload gitleaks report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: gitleaks-report | |
| path: gitleaks-report.json | |
| retention-days: 30 | |
| vulnerabilities: | |
| name: Vulnerability Scanning | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: cachix/install-nix-action@v25 | |
| with: | |
| nix_path: nixpkgs=channel:nixos-unstable | |
| - name: Trivy filesystem scan | |
| id: trivy-fs | |
| continue-on-error: true | |
| run: | | |
| nix shell nixpkgs#trivy --command \ | |
| trivy fs --severity CRITICAL,HIGH \ | |
| --format json \ | |
| --output trivy-fs-report.json \ | |
| . | |
| - name: Trivy repository scan | |
| id: trivy-repo | |
| continue-on-error: true | |
| env: | |
| REPO_URL: ${{ github.repository }} | |
| run: | | |
| nix shell nixpkgs#trivy --command \ | |
| trivy repo --severity CRITICAL,HIGH \ | |
| --format json \ | |
| --output trivy-repo-report.json \ | |
| "https://github.com/${REPO_URL}" | |
| - name: Upload trivy reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: trivy-reports | |
| path: trivy-*.json | |
| retention-days: 30 | |
| license-check: | |
| name: Dependency License Check | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: cachix/install-nix-action@v25 | |
| with: | |
| nix_path: nixpkgs=channel:nixos-unstable | |
| - name: Check nix package licenses | |
| continue-on-error: true | |
| run: | | |
| echo "Checking Nix package licenses..." | |
| nix eval --json '.#nixosConfigurations.nixos' \ | |
| --apply 'x: builtins.attrNames x' \ | |
| > /tmp/packages.json 2>/dev/null || \ | |
| echo "License check requires full evaluation (skipped for speed)" | |
| sbom: | |
| name: Generate SBOM | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: cachix/install-nix-action@v25 | |
| with: | |
| nix_path: nixpkgs=channel:nixos-unstable | |
| - name: Generate software bill of materials | |
| continue-on-error: true | |
| run: | | |
| # Generate SBOM using Trivy (simpler than cyclonedx-nix) | |
| nix shell nixpkgs#trivy --command \ | |
| trivy sbom --format cyclonedx \ | |
| --output sbom.cyclonedx.json \ | |
| . || echo "SBOM generation skipped" | |
| - name: Upload SBOM | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sbom | |
| path: sbom.*.json | |
| retention-days: 30 | |
| summary: | |
| name: Security Summary | |
| runs-on: ubuntu-latest | |
| needs: [secrets, vulnerabilities, license-check, sbom] | |
| if: always() | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Download all reports | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: reports | |
| - name: Generate security summary | |
| env: | |
| SECRETS_RESULT: ${{ needs.secrets.result }} | |
| VULNS_RESULT: ${{ needs.vulnerabilities.result }} | |
| LICENSE_RESULT: ${{ needs.license-check.result }} | |
| SBOM_RESULT: ${{ needs.sbom.result }} | |
| run: | | |
| echo "## Security Scan Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Scan Date**: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Status" >> $GITHUB_STEP_SUMMARY | |
| echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Secret Detection | $SECRETS_RESULT |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Vulnerability Scan | $VULNS_RESULT |" >> $GITHUB_STEP_SUMMARY | |
| echo "| License Check | $LICENSE_RESULT |" >> $GITHUB_STEP_SUMMARY | |
| echo "| SBOM Generation | $SBOM_RESULT |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Artifacts" >> $GITHUB_STEP_SUMMARY | |
| echo "- Gitleaks report: Available in Actions artifacts" >> $GITHUB_STEP_SUMMARY | |
| echo "- Trivy reports: Available in Actions artifacts" >> $GITHUB_STEP_SUMMARY | |
| echo "- SBOM: Available in Actions artifacts" >> $GITHUB_STEP_SUMMARY | |
| - name: Fail if critical issues found | |
| env: | |
| SECRETS_RESULT: ${{ needs.secrets.result }} | |
| VULNS_RESULT: ${{ needs.vulnerabilities.result }} | |
| run: | | |
| if [ "$SECRETS_RESULT" = "failure" ] || [ "$VULNS_RESULT" = "failure" ]; then | |
| echo "::error::Security scan found critical issues" | |
| exit 1 | |
| fi |