Skip to content

Merge pull request #1086 from peterjoshua482-netizen/fix/market-reent… #1

Merge pull request #1086 from peterjoshua482-netizen/fix/market-reent…

Merge pull request #1086 from peterjoshua482-netizen/fix/market-reent… #1

name: Security Scanning
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * 1'
jobs:
sast-sonarqube:
name: SAST - SonarQube
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Build backend
run: npm run build --workspace=apps/backend
- name: Run backend tests with coverage
run: npx jest --coverage --passWithNoTests --coverageReporters=lcov
working-directory: apps/backend
continue-on-error: true
- name: Run frontend tests with coverage
run: npx jest --coverage --passWithNoTests --coverageReporters=lcov
working-directory: apps/frontend
continue-on-error: true
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v3
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
continue-on-error: true
container-scanning:
name: Container Scanning - Trivy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build backend image
uses: docker/build-push-action@v5
with:
context: .
file: apps/backend/Dockerfile
push: false
tags: brain-storm-backend:scan
load: true
- name: Scan backend image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: brain-storm-backend:scan
format: sarif
output: trivy-backend.sarif
severity: CRITICAL,HIGH
exit-code: '0'
- name: Build frontend image
uses: docker/build-push-action@v5
with:
context: .
file: apps/frontend/Dockerfile
push: false
tags: brain-storm-frontend:scan
load: true
continue-on-error: true
- name: Scan frontend image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: brain-storm-frontend:scan
format: sarif
output: trivy-frontend.sarif
severity: CRITICAL,HIGH
exit-code: '0'
continue-on-error: true
- name: Upload Trivy SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-backend.sarif
continue-on-error: true
- name: Upload Trivy results as artifact
uses: actions/upload-artifact@v4
with:
name: trivy-scan-results
path: trivy-*.sarif
retention-days: 30
dast-scanning:
name: DAST - OWASP ZAP
runs-on: ubuntu-latest
if: github.event_name == 'schedule' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: brain-storm
POSTGRES_USER: brain-storm
POSTGRES_DB: brain-storm
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Build backend
run: npm run build --workspace=apps/backend
- name: Start backend
run: npm run start:prod --workspace=apps/backend &
env:
DATABASE_HOST: localhost
DATABASE_PORT: 5432
DATABASE_USER: brain-storm
DATABASE_PASSWORD: brain-storm
DATABASE_NAME: brain-storm
REDIS_HOST: localhost
REDIS_PORT: 6379
NODE_ENV: production
JWT_SECRET: dast-test-secret-not-for-production
- name: Wait for backend
run: |
until curl -sf http://localhost:3000/health; do
sleep 2
done
- name: Run OWASP ZAP baseline scan
uses: zaproxy/action-baseline@v0.12.0
with:
target: 'http://localhost:3000'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a'
allow_issue_writing: false
fail_action: false
- name: Upload ZAP report
uses: actions/upload-artifact@v4
if: always()
with:
name: zap-scan-report
path: report_html.html
retention-days: 30
security-gates:
name: Security Gates - Fail on Critical
runs-on: ubuntu-latest
needs: [sast-sonarqube, container-scanning, dast-scanning]
if: always()
steps:
- name: Check for critical vulnerabilities
run: |
echo "## Security Gate Check" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.sast-sonarqube.result }}" == "failure" ]; then
echo "❌ SAST scan failed - critical issues detected" >> $GITHUB_STEP_SUMMARY
exit 1
fi
if [ "${{ needs.container-scanning.result }}" == "failure" ]; then
echo "❌ Container scan failed - critical vulnerabilities detected" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "✅ All security gates passed" >> $GITHUB_STEP_SUMMARY
vulnerability-tracking:
name: Vulnerability Tracking Report
runs-on: ubuntu-latest
needs: [sast-sonarqube, container-scanning, dast-scanning]
if: always()
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all scan artifacts
uses: actions/download-artifact@v4
with:
path: security-artifacts/
continue-on-error: true
- name: Generate comprehensive security report
run: |
mkdir -p security-reports
cat > security-reports/vulnerability-report.md << EOF
# Comprehensive Security Report
**Date:** $(date -u +"%Y-%m-%d %H:%M UTC")
**Run:** ${{ github.run_id }}
**Branch:** ${{ github.ref_name }}
**Commit:** ${{ github.sha }}
## Scan Results Summary
| Scanner | Status | Type | Coverage |
|---------|--------|------|----------|
| SonarQube | ${{ needs.sast-sonarqube.result }} | SAST | Code Quality & Vulnerabilities |
| Trivy | ${{ needs.container-scanning.result }} | Container | Image Vulnerabilities |
| OWASP ZAP | ${{ needs.dast-scanning.result }} | DAST | API Security |
## Severity Levels & SLAs
- **CRITICAL**: Immediate remediation required — blocks deployment
- **HIGH**: Remediate within 7 days
- **MEDIUM**: Remediate within 30 days
- **LOW**: Track and remediate opportunistically
## Security Scanning Coverage
### SAST (Static Application Security Testing)
- Code quality analysis via SonarQube
- Dependency vulnerability detection
- Code coverage metrics
### Container Scanning
- Base image vulnerability scanning
- Runtime dependency analysis
- Configuration security checks
### DAST (Dynamic Application Security Testing)
- API endpoint security testing
- Authentication/Authorization validation
- Input validation and injection testing
## Actions Required
1. Review full reports in workflow artifacts
2. Create GitHub issues for HIGH or CRITICAL findings
3. Link issues to security milestone
4. Update security tracking dashboard
## References
- [Dependency Vulnerability Scanning](.github/workflows/dependency-vulnerability-scanning.yml)
- [Security Best Practices](docs/security-best-practices.md)
- [Security Audit](docs/security-audit.md)
- [Security Guidelines](docs/security-guidelines.md)
EOF
cat security-reports/vulnerability-report.md
- name: Upload comprehensive security report
uses: actions/upload-artifact@v4
with:
name: comprehensive-security-report
path: security-reports/
retention-days: 90
- name: Post security summary to PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('security-reports/vulnerability-report.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🔒 Security Scan Results\n\n${report}`
});
- name: Open issue on critical findings
if: ${{ (needs.sast-sonarqube.result == 'failure' || needs.container-scanning.result == 'failure') && github.event_name == 'schedule' }}
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'Security: Critical vulnerabilities detected in automated scans',
body: `Automated security scans detected critical vulnerabilities.\n\nWorkflow run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}\n\nReview scan artifacts and remediate before next release.`,
labels: ['security', 'critical', 'automated-scan']
});