name: Security Audit on: schedule: - cron: '0 0 * * *' # Daily at midnight UTC push: branches: [ main, master ] pull_request: branches: [ main, master ] workflow_dispatch: # Allow manual trigger env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 jobs: audit: name: Security Audit runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Setup Rust cache uses: Swatinem/rust-cache@v2 - name: Install cargo-audit run: cargo install --locked cargo-audit - name: Run security audit run: cargo audit - name: Check for vulnerable dependencies run: | echo "Checking for known security vulnerabilities..." cargo audit --json > audit-results.json # Check if vulnerabilities were found VULN_COUNT=$(jq '.vulnerabilities.count' audit-results.json 2>/dev/null || echo "0") if [ "$VULN_COUNT" -gt 0 ]; then echo "❌ Found $VULN_COUNT vulnerabilities" cat audit-results.json | jq '.vulnerabilities.list' exit 1 else echo "✅ No vulnerabilities found" fi - name: Upload audit results uses: actions/upload-artifact@v4 if: always() with: name: security-audit-results path: audit-results.json retention-days: 90 dependency-check: name: Dependency Security Check runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Setup Rust cache uses: Swatinem/rust-cache@v2 - name: Install cargo-deny run: cargo install --locked cargo-deny - name: Check dependency licenses and security run: | # Create deny.toml if it doesn't exist if [ ! -f "deny.toml" ]; then echo "Creating deny.toml configuration..." cat > deny.toml << 'EOF' [advisories] vulnerability = "deny" unmaintained = "warn" unsound = "deny" yanked = "deny" [licenses] unlicensed = "deny" copyleft = "deny" allow = [ "MIT", "Apache-2.0", "BSD-3-Clause", "ISC", "Unicode-DFS-2016" ] confidence-threshold = 0.8 [bans] multiple-versions = "warn" wildcards = "deny" EOF fi cargo deny check outdated-check: name: Outdated Dependencies Check runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Setup Rust cache uses: Swatinem/rust-cache@v2 - name: Install cargo-outdated run: cargo install --locked cargo-outdated - name: Check for outdated dependencies run: | echo "Checking for outdated dependencies..." cargo outdated --format json > outdated.json || true # Display outdated dependencies cat outdated.json | jq '.' - name: Upload outdated report uses: actions/upload-artifact@v4 with: name: outdated-dependencies path: outdated.json retention-days: 30 security-summary: name: Security Summary runs-on: ubuntu-latest needs: [audit, dependency-check, outdated-check] if: always() steps: - name: Generate security summary run: | echo "## 🔒 Security Audit Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Audit Results:" >> $GITHUB_STEP_SUMMARY echo "- **Vulnerability Scan**: ${{ needs.audit.result == 'success' && '✅ PASSED' || '❌ FAILED' }}" >> $GITHUB_STEP_SUMMARY echo "- **Dependency Check**: ${{ needs.dependency-check.result == 'success' && '✅ PASSED' || '❌ FAILED' }}" >> $GITHUB_STEP_SUMMARY echo "- **Outdated Check**: ${{ needs.outdated-check.result == 'success' && '✅ PASSED' || (needs.outdated-check.result == 'failure' && '⚠️ WARNING' || '⏭️ SKIPPED') }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Audit Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> $GITHUB_STEP_SUMMARY echo "**Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY - name: Check critical failures run: | if [[ "${{ needs.audit.result }}" == "failure" || "${{ needs.dependency-check.result }}" == "failure" ]]; then echo "❌ Critical security issues detected" exit 1 fi