Files
bambuddy/.github/workflows/security.yml
T
2026-01-26 15:53:54 +01:00

224 lines
7.4 KiB
YAML

name: Security Audit
on:
schedule:
# Run weekly on Monday at 6:00 UTC
- cron: '0 6 * * 1'
workflow_dispatch:
# Allow manual trigger
env:
PYTHON_VERSION: '3.11'
NODE_VERSION: '20'
# Default permissions for all jobs
permissions:
contents: read
jobs:
backend-audit:
name: Backend Security Audit
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pip-audit
- name: Run pip-audit
id: pip-audit
run: |
pip-audit --desc on --format json --output pip-audit-results.json || echo "vulnerabilities_found=true" >> $GITHUB_OUTPUT
pip-audit --desc on || true
- name: Upload audit results
if: always()
uses: actions/upload-artifact@v4
with:
name: pip-audit-results
path: pip-audit-results.json
retention-days: 30
- name: Create issue on vulnerability
if: steps.pip-audit.outputs.vulnerabilities_found == 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('pip-audit-results.json', 'utf8'));
// Build vulnerability table
let table = '| Package | Version | Vulnerability | Fix Version |\n';
table += '|---------|---------|---------------|-------------|\n';
for (const vuln of results.dependencies || []) {
for (const v of vuln.vulns || []) {
table += `| ${vuln.name} | ${vuln.version} | ${v.id} | ${v.fix_versions?.join(', ') || 'N/A'} |\n`;
}
}
const title = `Security Alert: ${results.dependencies?.reduce((acc, d) => acc + (d.vulns?.length || 0), 0) || 0} Python vulnerabilities found`;
// Check for existing open issue
const existingIssues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'security,automated'
});
const existingIssue = existingIssues.data.find(i => i.title.startsWith('Security Alert:') && i.title.includes('Python'));
const body = `## Automated Security Audit Results
The weekly security audit found vulnerabilities in Python dependencies.
${table}
### Recommended Actions
1. Review each vulnerability
2. Update affected packages: \`pip install --upgrade <package>\`
3. Run \`pip-audit\` locally to verify fixes
4. Close this issue when resolved
---
*This issue was automatically created by the security audit workflow.*`;
if (existingIssue) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: body
});
console.log(`Updated existing issue #${existingIssue.number}`);
} else {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['security', 'automated', 'dependencies']
});
console.log('Created new security issue');
}
frontend-audit:
name: Frontend Security Audit
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
working-directory: frontend
run: npm ci
- name: Run npm audit
id: npm-audit
working-directory: frontend
run: |
npm audit --json > npm-audit-results.json || echo "vulnerabilities_found=true" >> $GITHUB_OUTPUT
npm audit --audit-level=high || true
- name: Upload audit results
if: always()
uses: actions/upload-artifact@v4
with:
name: npm-audit-results
path: frontend/npm-audit-results.json
retention-days: 30
- name: Create issue on vulnerability
if: steps.npm-audit.outputs.vulnerabilities_found == 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('frontend/npm-audit-results.json', 'utf8'));
const vulns = results.vulnerabilities || {};
const vulnCount = Object.keys(vulns).length;
if (vulnCount === 0) {
console.log('No vulnerabilities to report');
return;
}
// Build vulnerability table
let table = '| Package | Severity | Via | Fix |\n';
table += '|---------|----------|-----|-----|\n';
for (const [name, info] of Object.entries(vulns)) {
const via = Array.isArray(info.via) ? info.via.map(v => typeof v === 'string' ? v : v.name).join(', ') : info.via;
table += `| ${name} | ${info.severity} | ${via} | ${info.fixAvailable ? 'Yes' : 'No'} |\n`;
}
const title = `Security Alert: ${vulnCount} npm vulnerabilities found`;
// Check for existing open issue
const existingIssues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'security,automated'
});
const existingIssue = existingIssues.data.find(i => i.title.startsWith('Security Alert:') && i.title.includes('npm'));
const body = `## Automated Security Audit Results
The weekly security audit found vulnerabilities in npm dependencies.
${table}
### Recommended Actions
1. Review each vulnerability: \`npm audit\`
2. Auto-fix if possible: \`npm audit fix\`
3. Manual fix for breaking changes: \`npm audit fix --force\` (review changes!)
4. Close this issue when resolved
---
*This issue was automatically created by the security audit workflow.*`;
if (existingIssue) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: body
});
console.log(`Updated existing issue #${existingIssue.number}`);
} else {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['security', 'automated', 'dependencies']
});
console.log('Created new security issue');
}