Security Testing Pipeline #5
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 Testing Pipeline | |
| on: | |
| push: | |
| branches: [main, 'feature/**'] | |
| pull_request: | |
| branches: [main] | |
| schedule: | |
| # Run nightly on main | |
| - cron: '0 2 * * *' | |
| jobs: | |
| secret-scan: | |
| name: Secret Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.3.0 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run PII / secrets scan (pii-scan.mjs) | |
| run: node scripts/pii-scan.mjs | |
| - name: Run gitleaks | |
| uses: gitleaks/gitleaks-action@b6c5701469c3e8b8f2ec5b3c81bda3f28b673af6 # v2.3.6 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_CONFIG: .gitleaks.toml | |
| sast: | |
| name: SAST – Static Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.3.0 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run SAST + pipeline tests | |
| run: npx vitest run backend/tests/security-pipeline.test.js --reporter=verbose | |
| env: | |
| NODE_ENV: test | |
| STELLAR_NETWORK: testnet | |
| HORIZON_URL: https://horizon-testnet.stellar.org | |
| - name: Upload security report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: security-report-${{ github.sha }} | |
| path: test-reports/ | |
| retention-days: 30 | |
| dependency-scan: | |
| name: Dependency Vulnerability Scan (OWASP / audit-ci) | |
| # Issue #774 — upgraded from plain npm audit to audit-ci for structured | |
| # reporting, configurable thresholds, and JSON artefacts. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.3.0 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install root dependencies | |
| run: npm ci | |
| - name: Install backend dependencies | |
| run: npm ci | |
| working-directory: backend | |
| - name: Install frontend dependencies | |
| run: npm ci | |
| working-directory: frontend | |
| # audit-ci wraps npm audit with configurable CVSS thresholds and structured JSON output. | |
| # --high fails on CVSS >= 7.0 (HIGH and CRITICAL). | |
| - name: audit-ci — root workspace | |
| run: npx audit-ci@^7 --high --output-format json 2>&1 | tee audit-root.json; exit ${PIPESTATUS[0]} | |
| - name: audit-ci — backend | |
| run: npx audit-ci@^7 --high --output-format json 2>&1 | tee audit-backend.json; exit ${PIPESTATUS[0]} | |
| working-directory: backend | |
| - name: audit-ci — frontend | |
| run: npx audit-ci@^7 --high --output-format json 2>&1 | tee audit-frontend.json; exit ${PIPESTATUS[0]} | |
| working-directory: frontend | |
| - name: Upload dependency scan reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dependency-scan-reports-${{ github.sha }} | |
| path: | | |
| audit-root.json | |
| backend/audit-backend.json | |
| frontend/audit-frontend.json | |
| retention-days: 30 | |
| security-gate: | |
| name: Security Gate | |
| runs-on: ubuntu-latest | |
| needs: [secret-scan, sast, dependency-scan] | |
| if: always() | |
| steps: | |
| - name: Check security gate | |
| run: | | |
| if [ "${{ needs.secret-scan.result }}" != "success" ]; then | |
| echo "❌ Secret scanning stage failed" | |
| exit 1 | |
| fi | |
| if [ "${{ needs.sast.result }}" != "success" ]; then | |
| echo "❌ SAST stage failed" | |
| exit 1 | |
| fi | |
| if [ "${{ needs.dependency-scan.result }}" != "success" ]; then | |
| echo "❌ Dependency scan stage failed" | |
| exit 1 | |
| fi | |
| echo "✅ Security gate passed" | |
| - name: Comment PR on security failure | |
| if: failure() && github.event_name == 'pull_request' | |
| uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: '🔒 **Security gate failed.** Review the `security-report` artifact for SAST findings or dependency vulnerabilities before merging.' | |
| }) |