Security Scan #172
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security Scan | |
| on: | |
| schedule: | |
| # Run daily at 2 AM UTC | |
| - cron: '0 2 * * *' | |
| push: | |
| branches: [ main, master, develop ] | |
| pull_request: | |
| branches: [ main, master, develop ] | |
| workflow_dispatch: # Allow manual triggering | |
| jobs: | |
| vulnerability-scan: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| security-events: write | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| # Use pip-audit for dependency scanning (no authentication required) | |
| pip install pip-audit bandit[toml] | |
| echo "π¦ Installed dependencies:" | |
| pip list | grep -E "(pip-audit|bandit)" | |
| echo "π§ pip-audit version:" | |
| pip-audit --version | |
| - name: Run pip-audit dependency vulnerability scan | |
| run: | | |
| echo "π Running pip-audit dependency vulnerability scan..." | |
| # Use pip-audit for dependency vulnerability scanning | |
| pip-audit --format=json --output=safety-report.json --requirement=requirements.txt || true | |
| if [ -f safety-report.json ] && [ -s safety-report.json ]; then | |
| echo "β pip-audit JSON report generated" | |
| echo "π Report size: $(wc -c < safety-report.json) bytes" | |
| else | |
| echo "β pip-audit JSON report not generated or empty" | |
| # Create a basic report structure if scan fails | |
| echo '{"vulnerabilities": [], "scan_target": "requirements.txt", "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > safety-report.json | |
| fi | |
| echo "Running pip-audit summary report..." | |
| pip-audit --requirement=requirements.txt || echo "pip-audit summary failed" | |
| - name: Run Bandit code security scan | |
| run: | | |
| echo "π Running Bandit code security scan..." | |
| bandit -r gefcore/ -f json -o bandit-report.json || true | |
| if [ -f bandit-report.json ]; then | |
| echo "β Bandit JSON report generated" | |
| else | |
| echo "β Bandit JSON report not generated" | |
| fi | |
| echo "Running Bandit severity check..." | |
| bandit -r gefcore/ --severity-level medium || true | |
| - name: Run Trivy filesystem scan | |
| uses: aquasecurity/trivy-action@0.24.0 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| exit-code: '0' # Don't fail the workflow on vulnerabilities | |
| - name: Check if Trivy SARIF file exists and is valid | |
| run: | | |
| if [ -f trivy-results.sarif ]; then | |
| echo "β Trivy SARIF file exists" | |
| # Check if file is not empty and has valid JSON structure | |
| if [ -s trivy-results.sarif ]; then | |
| echo "β Trivy SARIF file is not empty" | |
| # Basic JSON validation | |
| if python -m json.tool trivy-results.sarif >/dev/null 2>&1; then | |
| echo "β Trivy SARIF file has valid JSON structure" | |
| else | |
| echo "β Trivy SARIF file has invalid JSON structure" | |
| cat trivy-results.sarif | |
| fi | |
| else | |
| echo "β Trivy SARIF file is empty" | |
| fi | |
| else | |
| echo "β Trivy SARIF file does not exist" | |
| # Create an empty valid SARIF file as fallback | |
| echo '{ | |
| "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", | |
| "version": "2.1.0", | |
| "runs": [] | |
| }' > trivy-results.sarif | |
| echo "Created empty SARIF file as fallback" | |
| fi | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() && hashFiles('trivy-results.sarif') != '' | |
| with: | |
| sarif_file: trivy-results.sarif | |
| category: 'trivy-fs-scan' | |
| continue-on-error: true | |
| - name: Check SARIF upload status | |
| if: always() | |
| run: | | |
| if [ -f trivy-results.sarif ]; then | |
| echo "π SARIF file size: $(wc -c < trivy-results.sarif) bytes" | |
| echo "π SARIF file lines: $(wc -l < trivy-results.sarif) lines" | |
| # Show first few lines to check structure | |
| echo "π SARIF file structure (first 10 lines):" | |
| head -n 10 trivy-results.sarif | |
| else | |
| echo "β SARIF file not found for upload verification" | |
| fi | |
| - name: Upload security scan artifacts | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: security-scan-reports | |
| path: | | |
| safety-report.json | |
| bandit-report.json | |
| trivy-results.sarif | |
| retention-days: 30 | |
| - name: Create security summary | |
| if: always() | |
| run: | | |
| echo "## π Security Scan Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "*Scan completed on $(date -u)*" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### π‘οΈ pip-audit (Dependency Vulnerabilities)" >> $GITHUB_STEP_SUMMARY | |
| if [ -f safety-report.json ]; then | |
| echo "β pip-audit scan completed successfully" >> $GITHUB_STEP_SUMMARY | |
| # Extract vulnerability count if possible | |
| if command -v jq >/dev/null 2>&1; then | |
| VULN_COUNT=$(jq -r '.vulnerabilities | length // "unknown"' safety-report.json 2>/dev/null || echo "unknown") | |
| echo "π Vulnerabilities found: $VULN_COUNT" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "β pip-audit scan failed - check logs for details" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### π Bandit (Code Security)" >> $GITHUB_STEP_SUMMARY | |
| if [ -f bandit-report.json ]; then | |
| echo "β Bandit scan completed successfully" >> $GITHUB_STEP_SUMMARY | |
| # Extract issue count if possible | |
| if command -v jq >/dev/null 2>&1; then | |
| ISSUE_COUNT=$(jq -r '.results | length' bandit-report.json 2>/dev/null || echo "unknown") | |
| echo "π Security issues found: $ISSUE_COUNT" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "β Bandit scan failed - check logs for details" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### ποΈ Trivy (Container/Filesystem Security)" >> $GITHUB_STEP_SUMMARY | |
| if [ -f trivy-results.sarif ]; then | |
| FILE_SIZE=$(wc -c < trivy-results.sarif) | |
| echo "β Trivy scan completed successfully" >> $GITHUB_STEP_SUMMARY | |
| echo "π SARIF file size: ${FILE_SIZE} bytes" >> $GITHUB_STEP_SUMMARY | |
| if [ "$FILE_SIZE" -gt 100 ]; then | |
| echo "π€ Results uploaded to Security tab" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "β οΈ SARIF file seems too small - may be empty" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "β Trivy scan failed - SARIF file not generated" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "π All scan reports are available as workflow artifacts." >> $GITHUB_STEP_SUMMARY |