Skip to content

Security Testing Pipeline #5

Security Testing Pipeline

Security Testing Pipeline #5

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.'
})