Files
wifi-densepose/.github/workflows/security-scan.yml
ruv 4b36d7c9d7 fix: add feat/* branch pattern to CI workflow triggers
Push events for feat/ branches were not matching the feature/ glob,
causing CI to skip on all feat/* branches.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-01 01:41:36 -05:00

449 lines
13 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Security Scanning
on:
push:
branches: [ main, develop, 'feat/*' ]
pull_request:
branches: [ main, develop ]
schedule:
# Run security scans daily at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch:
env:
PYTHON_VERSION: '3.11'
jobs:
# Static Application Security Testing (SAST)
sast:
name: Static Application Security Testing
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install bandit semgrep safety
- name: Run Bandit security scan
run: |
bandit -r src/ -f sarif -o bandit-results.sarif
continue-on-error: true
- name: Upload Bandit results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: bandit-results.sarif
category: bandit
- name: Run Semgrep security scan
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
p/python
p/docker
p/kubernetes
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- name: Generate Semgrep SARIF
run: |
semgrep --config=p/security-audit --config=p/secrets --config=p/python --sarif --output=semgrep.sarif src/
continue-on-error: true
- name: Upload Semgrep results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: semgrep.sarif
category: semgrep
# Dependency vulnerability scanning
dependency-scan:
name: Dependency Vulnerability Scan
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install safety pip-audit
- name: Run Safety check
run: |
safety check --json --output safety-report.json
continue-on-error: true
- name: Run pip-audit
run: |
pip-audit --format=json --output=pip-audit-report.json
continue-on-error: true
- name: Run Snyk vulnerability scan
uses: snyk/actions/python@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --sarif-file-output=snyk-results.sarif
continue-on-error: true
- name: Upload Snyk results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: snyk-results.sarif
category: snyk
- name: Upload vulnerability reports
uses: actions/upload-artifact@v4
if: always()
with:
name: vulnerability-reports
path: |
safety-report.json
pip-audit-report.json
snyk-results.sarif
# Container security scanning
container-scan:
name: Container Security Scan
runs-on: ubuntu-latest
needs: []
if: github.event_name == 'push' || github.event_name == 'schedule'
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image for scanning
uses: docker/build-push-action@v5
with:
context: .
target: production
load: true
tags: wifi-densepose:scan
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'wifi-densepose:scan'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
category: trivy
- name: Run Grype vulnerability scanner
uses: anchore/scan-action@v3
id: grype-scan
with:
image: 'wifi-densepose:scan'
fail-build: false
severity-cutoff: high
output-format: sarif
- name: Upload Grype results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: ${{ steps.grype-scan.outputs.sarif }}
category: grype
- name: Run Docker Scout
uses: docker/scout-action@v1
if: always()
with:
command: cves
image: wifi-densepose:scan
sarif-file: scout-results.sarif
summary: true
- name: Upload Docker Scout results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: scout-results.sarif
category: docker-scout
# Infrastructure as Code security scanning
iac-scan:
name: Infrastructure Security Scan
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Checkov IaC scan
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: kubernetes,dockerfile,terraform,ansible
output_format: sarif
output_file_path: checkov-results.sarif
quiet: true
soft_fail: true
- name: Upload Checkov results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: checkov-results.sarif
category: checkov
- name: Run Terrascan IaC scan
uses: tenable/terrascan-action@main
with:
iac_type: 'k8s'
iac_version: 'v1'
policy_type: 'k8s'
only_warn: true
sarif_upload: true
- name: Run KICS IaC scan
uses: checkmarx/kics-github-action@master
with:
path: '.'
output_path: kics-results
output_formats: 'sarif'
exclude_paths: '.git,node_modules'
exclude_queries: 'a7ef1e8c-fbf8-4ac1-b8c7-2c3b0e6c6c6c'
- name: Upload KICS results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: kics-results/results.sarif
category: kics
# Secret scanning
secret-scan:
name: Secret Scanning
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run TruffleHog secret scan
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: main
head: HEAD
extra_args: --debug --only-verified
- name: Run GitLeaks secret scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
- name: Run detect-secrets
run: |
pip install detect-secrets
detect-secrets scan --all-files --baseline .secrets.baseline
detect-secrets audit .secrets.baseline
continue-on-error: true
# License compliance scanning
license-scan:
name: License Compliance Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pip-licenses licensecheck
- name: Run license check
run: |
pip-licenses --format=json --output-file=licenses.json
licensecheck --zero
- name: Upload license report
uses: actions/upload-artifact@v4
with:
name: license-report
path: licenses.json
# Security policy compliance
compliance-check:
name: Security Policy Compliance
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check security policy files
run: |
# Check for required security files
files=("SECURITY.md" ".github/SECURITY.md" "docs/SECURITY.md")
found=false
for file in "${files[@]}"; do
if [[ -f "$file" ]]; then
echo "✅ Found security policy: $file"
found=true
break
fi
done
if [[ "$found" == false ]]; then
echo "❌ No security policy found. Please create SECURITY.md"
exit 1
fi
- name: Check for security headers in code
run: |
# Check for security-related configurations
grep -r "X-Frame-Options\|X-Content-Type-Options\|X-XSS-Protection\|Content-Security-Policy" src/ || echo "⚠️ Consider adding security headers"
- name: Validate Kubernetes security contexts
run: |
# Check for security contexts in Kubernetes manifests
if [[ -d "k8s" ]]; then
if find k8s/ -name "*.yaml" -exec grep -l "securityContext" {} \; | wc -l | grep -q "^0$"; then
echo "⚠️ No security contexts found in Kubernetes manifests"
else
echo "✅ Security contexts found in Kubernetes manifests"
fi
else
echo " No k8s/ directory found — skipping Kubernetes security context check"
fi
# Notification and reporting
security-report:
name: Security Report
runs-on: ubuntu-latest
needs: [sast, dependency-scan, container-scan, iac-scan, secret-scan, license-scan, compliance-check]
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Generate security summary
run: |
echo "# Security Scan Summary" > security-summary.md
echo "" >> security-summary.md
echo "## Scan Results" >> security-summary.md
echo "- SAST: ${{ needs.sast.result }}" >> security-summary.md
echo "- Dependency Scan: ${{ needs.dependency-scan.result }}" >> security-summary.md
echo "- Container Scan: ${{ needs.container-scan.result }}" >> security-summary.md
echo "- IaC Scan: ${{ needs.iac-scan.result }}" >> security-summary.md
echo "- Secret Scan: ${{ needs.secret-scan.result }}" >> security-summary.md
echo "- License Scan: ${{ needs.license-scan.result }}" >> security-summary.md
echo "- Compliance Check: ${{ needs.compliance-check.result }}" >> security-summary.md
echo "" >> security-summary.md
echo "Generated on: $(date)" >> security-summary.md
- name: Upload security summary
uses: actions/upload-artifact@v4
with:
name: security-summary
path: security-summary.md
- name: Notify security team on critical findings
if: ${{ secrets.SECURITY_SLACK_WEBHOOK_URL != '' && (needs.sast.result == 'failure' || needs.dependency-scan.result == 'failure' || needs.container-scan.result == 'failure') }}
uses: 8398a7/action-slack@v3
with:
status: failure
channel: '#security'
text: |
🚨 Critical security findings detected!
Repository: ${{ github.repository }}
Branch: ${{ github.ref }}
Workflow: ${{ github.workflow }}
Please review the security scan results immediately.
env:
SLACK_WEBHOOK_URL: ${{ secrets.SECURITY_SLACK_WEBHOOK_URL }}
- name: Create security issue on critical findings
if: needs.sast.result == 'failure' || needs.dependency-scan.result == 'failure'
uses: actions/github-script@v6
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Security Scan Failures - ${new Date().toISOString()}`,
body: `
## Security Scan Failures Detected
**Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
**Branch:** ${{ github.ref }}
**Failed Scans:**
- SAST: ${{ needs.sast.result }}
- Dependency Scan: ${{ needs.dependency-scan.result }}
- Container Scan: ${{ needs.container-scan.result }}
**Action Required:**
- [ ] Review security scan results
- [ ] Address critical vulnerabilities
- [ ] Update dependencies if needed
- [ ] Re-run security scans
**Security Dashboard:** Check the Security tab for detailed findings.
`,
labels: ['security', 'vulnerability', 'urgent']
})