Skip to content

Security Scan

Security Scan #30

Workflow file for this run

name: Security Scan
on:
schedule:
- cron: '0 2 * * 1' # Run at 2 AM every Monday
workflow_dispatch: # Allow manual triggering
push:
branches:
- main
- 'release-*'
paths:
- '**/*.js'
- '**/*.jsx'
- '**/*.ts'
- '**/*.tsx'
- 'package*.json'
permissions:
contents: read
security-events: write
issues: write
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
# Generate Software Bill of Materials (SBOM)
- name: Generate SBOM with CycloneDX
uses: CycloneDX/gh-node-module-generatebom@v1
with:
path: ./
output: cyclonedx.json
- name: Generate SBOM with Syft
uses: anchore/sbom-action@v0
with:
format: spdx-json
output-file: ./syft-sbom.json
# Upload SBOM files
- name: Upload SBOM files
uses: actions/upload-artifact@v4
with:
name: sbom-files
path: |
cyclonedx.json
syft-sbom.json
retention-days: 90
timeout-minutes: 5 # Prevent artifact upload from hanging
# Run npm audit to check for vulnerable dependencies
- name: Run npm audit
run: npm audit --production
continue-on-error: true
# Run Snyk vulnerability scan
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
# Run Trivy vulnerability scanner
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
# Static code analysis with ESLint security plugins
- name: Install ESLint and security plugins
run: |
npm install -g eslint
npm install -g eslint-plugin-security eslint-plugin-sonarjs eslint-plugin-node
- name: Run ESLint security scan
run: |
eslint --plugin security,sonarjs --ext .js,.jsx,.ts,.tsx src/ server/ --no-eslintrc --config .github/workflows/eslint-security.json -f json > eslint-report.json || true
# Secret scanning
- name: Secret Scanning with GitLeaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
continue-on-error: true
# Check for dependency confusion vulnerabilities
- name: Dependency Confusion Check
run: |
npm install -g @jwt/confusion-scanner
npx @jwt/confusion-scanner --path ./ --output dependency-confusion-report.json
continue-on-error: true
# Check package.json for issues
- name: Package.json security audit
uses: lirantal/lockfile-lint-action@v4.7.1
with:
path: package-lock.json
allowed-hosts: npm
validate-https: true
allowed-schemes: "https:"
continue-on-error: true
# Run NodeJsScan for security issues
- name: Install NodeJsScan
run: pip install nodejsscan
- name: Run NodeJsScan
run: nodejsscan -d ./ -o nodejsscan-report.json
continue-on-error: true
# OWASP ZAP Baseline Scan
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.9.0
with:
target: 'http://localhost:3000'
rules_file_name: '.github/workflows/zap-rules.tsv'
cmd_options: '-a'
env:
API_URL: 'http://localhost:5000/api'
# Upload scan results as artifacts
- name: Upload scan results
uses: actions/upload-artifact@v4
with:
name: security-scan-reports
path: |
eslint-report.json
nodejsscan-report.json
zap-report.html
trivy-results.sarif
dependency-confusion-report.json
retention-days: 30
timeout-minutes: 5 # Prevent artifact upload from hanging
# License compliance scanning
- name: License Scanning
uses: fossas/fossa-action@main
with:
api-key: ${{ secrets.FOSSA_API_KEY }}
continue-on-error: true
# Notify on critical findings
- name: Check for critical vulnerabilities
id: check_critical
run: |
critical_count=$(grep -c "CRITICAL" trivy-results.sarif || echo "0")
if [ "$critical_count" -gt "0" ]; then
echo "has_critical=true" >> $GITHUB_OUTPUT
else
echo "has_critical=false" >> $GITHUB_OUTPUT
fi
- name: Create GitHub issue for critical vulnerabilities
if: steps.check_critical.outputs.has_critical == 'true'
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '🚨 Critical Security Vulnerabilities Detected',
body: 'The security scan has detected critical vulnerabilities. Please check the security scan artifacts in GitHub Actions run #' + context.runId,
labels: ['security', 'critical']
})