Skip to content

dev v2.0.3

dev v2.0.3 #172

Workflow file for this run

name: Security Scan
on:
pull_request:
branches: [ '*' ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
security-scan:
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
pull-requests: write
steps:
- name: 1. Checkout repository code
uses: actions/checkout@v6
- name: 2. Set up Python 3.14 with caching
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: 'pip'
- name: 3. Install security tools
run: pip install bandit[sarif]
- name: 4. Run Bandit Scan
working-directory: ./backend
run: |
echo "Running Bandit security scan..."
if bandit -r . -f json -o bandit-results.json --configfile pyproject.toml; then
echo "BANDIT_PASSED=true" >> $GITHUB_ENV
echo "✅ No security issues found by Bandit"
else
echo "BANDIT_PASSED=false" >> $GITHUB_ENV
echo "⚠️ Bandit found security issues"
fi
bandit -r . -f sarif -o bandit-results.sarif --configfile pyproject.toml || true
continue-on-error: true
- name: 5. Upload Bandit SARIF to GitHub
if: always()
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: backend/bandit-results.sarif
continue-on-error: true
- name: 6. Create Security Summary
if: github.event_name == 'pull_request'
working-directory: ./backend
run: |
cat > ../security-report.md << 'EOL'
## 🔒 Security Scan Results
EOL
# Check actual issue count from JSON results instead of exit code
ACTUAL_ISSUES=0
if [ -f bandit-results.json ]; then
ACTUAL_ISSUES=$(python3 -c "import json; data=json.load(open('bandit-results.json')); metrics=data.get('metrics',{}); print(metrics.get('SEVERITY.HIGH',0) + metrics.get('SEVERITY.MEDIUM',0) + metrics.get('SEVERITY.LOW',0))" 2>/dev/null || echo "0")
fi
if [[ "$ACTUAL_ISSUES" == "0" ]]; then
cat >> ../security-report.md << 'EOL'
### ✅ Bandit: **Passed**
No security issues found. Your code passed all security checks! 🎉
EOL
else
cat >> ../security-report.md << 'EOL'
### ⚠️ Bandit: **Security Issues Found**
EOL
# Parse and display results if file exists
if [ -f bandit-results.json ]; then
echo '<details><summary>Click to view security findings</summary>' >> ../security-report.md
echo '' >> ../security-report.md
echo '```' >> ../security-report.md
python3 << 'PYTHON_SCRIPT' >> ../security-report.md 2>/dev/null || echo "Could not parse results" >> ../security-report.md
import json
import sys
try:
with open('bandit-results.json', 'r') as f:
data = json.load(f)
# Print metrics
metrics = data.get('metrics', {})
total_issues = sum([
metrics.get('SEVERITY.HIGH', 0),
metrics.get('SEVERITY.MEDIUM', 0),
metrics.get('SEVERITY.LOW', 0)
])
print(f'📊 Summary:')
print(f'Total issues: {total_issues}')
print(f'Files with issues: {metrics.get("files_with_issues", 0)}')
print(f'')
print(f'🔴 High severity: {metrics.get("SEVERITY.HIGH", 0)}')
print(f'🟡 Medium severity: {metrics.get("SEVERITY.MEDIUM", 0)}')
print(f'🟢 Low severity: {metrics.get("SEVERITY.LOW", 0)}')
print()
# Group results by severity
results = data.get('results', [])
high = [r for r in results if r['issue_severity'] == 'HIGH']
medium = [r for r in results if r['issue_severity'] == 'MEDIUM']
low = [r for r in results if r['issue_severity'] == 'LOW']
# Display high severity first (up to 5)
if high:
print('🔴 HIGH SEVERITY ISSUES:')
for i, result in enumerate(high[:5], 1):
print(f"{i}. {result['issue_text']}")
print(f" 📍 {result['filename']}:{result['line_number']}")
print(f" CWE: {result.get('issue_cwe', {}).get('id', 'N/A')}")
print()
if len(high) > 5:
print(f" ... and {len(high) - 5} more high severity issues")
print()
# Display medium severity (up to 3)
if medium:
print('🟡 MEDIUM SEVERITY ISSUES:')
for i, result in enumerate(medium[:3], 1):
print(f"{i}. {result['issue_text']}")
print(f" 📍 {result['filename']}:{result['line_number']}")
print()
if len(medium) > 3:
print(f" ... and {len(medium) - 3} more medium severity issues")
print()
# Display low severity count only if there are issues
if low:
print(f'🟢 LOW SEVERITY: {len(low)} issues found')
except Exception as e:
print(f'Error parsing bandit results: {str(e)}')
PYTHON_SCRIPT
echo '```' >> ../security-report.md
echo '</details>' >> ../security-report.md
echo '' >> ../security-report.md
echo '**Action Required:** Please review and fix the security issues before merging.' >> ../security-report.md
else
echo 'Could not find detailed results file.' >> ../security-report.md
fi
fi
cat >> ../security-report.md << 'EOL'
---
*Security scans help identify potential vulnerabilities in your code. [Learn more about Bandit](https://bandit.readthedocs.io/)*
<!-- security-scan-comment-marker -->
EOL
- name: 7. Post PR Comment
if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ github.event.pull_request.number }}
body-path: security-report.md
edit-mode: replace