Security Pipeline #20
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
| # Security CI/CD Pipeline | |
| # ======================= | |
| # Comprehensive security scanning for the GitHub Copilot Cybersecurity course | |
| # Course: GitHub Copilot for Cybersecurity Specialists | |
| # | |
| # - Secret detection (TruffleHog, GitLeaks) | |
| # - Dependency scanning (npm audit, Snyk) | |
| # - SAST (CodeQL, Semgrep) | |
| # - IaC scanning (Checkov, KICS) | |
| # - Container scanning (Trivy) | |
| # - Security gate enforcement | |
| name: Security Pipeline | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main] | |
| schedule: | |
| # Run security scans daily at 6 AM UTC | |
| - cron: '0 6 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| full_scan: | |
| description: 'Run full security scan including DAST' | |
| required: false | |
| default: 'false' | |
| type: boolean | |
| env: | |
| NODE_VERSION: '20' | |
| JAVA_VERSION: '21' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # =========================================================================== | |
| # Secret Detection - Prevent credential leaks | |
| # =========================================================================== | |
| secret-detection: | |
| name: Secret Detection | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: TruffleHog Scan | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| base: ${{ github.event.repository.default_branch }} | |
| head: HEAD | |
| extra_args: --only-verified | |
| - name: GitLeaks Scan | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # =========================================================================== | |
| # Dependency Scanning - Identify vulnerable packages | |
| # =========================================================================== | |
| dependency-scan: | |
| name: Dependency Vulnerability Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: NPM Audit (Root) | |
| run: | | |
| if [ -f package-lock.json ]; then | |
| npm audit --audit-level=high --json > npm-audit-root.json || true | |
| fi | |
| continue-on-error: true | |
| - name: NPM Audit (NodeGoat) | |
| working-directory: ./NodeGoat | |
| run: | | |
| if [ -f package-lock.json ]; then | |
| npm audit --audit-level=critical --json > ../npm-audit-nodegoat.json || true | |
| fi | |
| continue-on-error: true | |
| - name: Upload Audit Results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: npm-audit-results | |
| path: npm-audit-*.json | |
| retention-days: 30 | |
| # =========================================================================== | |
| # SAST - Semgrep Analysis | |
| # =========================================================================== | |
| sast-semgrep: | |
| name: Semgrep SAST | |
| runs-on: ubuntu-latest | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep scan \ | |
| --config p/security-audit \ | |
| --config p/owasp-top-ten \ | |
| --config p/nodejs \ | |
| --config p/javascript \ | |
| --sarif \ | |
| --output semgrep-results.sarif \ | |
| --error \ | |
| --exclude='**/node_modules/**' \ | |
| --exclude='**/vendor/**' \ | |
| --exclude='**/*.min.js' \ | |
| . || true | |
| - name: Upload Semgrep Results | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: semgrep-results.sarif | |
| continue-on-error: true | |
| # =========================================================================== | |
| # Infrastructure as Code Scanning | |
| # =========================================================================== | |
| iac-scan: | |
| name: IaC Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Checkov Scan | |
| uses: bridgecrewio/checkov-action@v12 | |
| with: | |
| directory: . | |
| framework: terraform | |
| output_format: cli,sarif | |
| output_file_path: console,checkov-results.sarif | |
| soft_fail: true | |
| skip_check: CKV_AWS_79,CKV_AWS_18 | |
| - name: Upload Checkov Results | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: checkov-results.sarif | |
| continue-on-error: true | |
| # =========================================================================== | |
| # Container Security Scanning | |
| # =========================================================================== | |
| container-scan: | |
| name: Container Security | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'pull_request' | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Trivy Filesystem Scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-fs-results.sarif' | |
| severity: 'CRITICAL,HIGH' | |
| ignore-unfixed: true | |
| - name: Upload Trivy Results | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: trivy-fs-results.sarif | |
| continue-on-error: true | |
| # =========================================================================== | |
| # Security Gate - Final approval step | |
| # =========================================================================== | |
| security-gate: | |
| name: Security Gate | |
| runs-on: ubuntu-latest | |
| needs: | |
| - secret-detection | |
| - dependency-scan | |
| - sast-semgrep | |
| - iac-scan | |
| if: always() | |
| steps: | |
| - name: Check Security Results | |
| run: | | |
| echo "## Security Scan Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Check each job status | |
| echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Secret Detection | ${{ needs.secret-detection.result == 'success' && 'Passed' || 'Review Required' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Dependency Scan | ${{ needs.dependency-scan.result == 'success' && 'Passed' || 'Review Required' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| SAST (Semgrep) | ${{ needs.sast-semgrep.result == 'success' && 'Passed' || 'Review Required' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| IaC Scan | ${{ needs.iac-scan.result == 'success' && 'Passed' || 'Review Required' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Note:** This repository contains intentionally vulnerable code for educational purposes." >> $GITHUB_STEP_SUMMARY | |
| - name: Gate Decision | |
| run: | | |
| # Only fail on secret detection failures (critical security issue) | |
| if [ "${{ needs.secret-detection.result }}" == "failure" ]; then | |
| echo "::error::Security gate failed - secrets detected in code" | |
| exit 1 | |
| fi | |
| echo "Security gate passed" |