Skip to content

Commit bbdbadd

Browse files
committed
feat: replace Grype with Trivy + GitHub Code Scanning
- Replace heavyweight Grype+Syft (3-5min) with Trivy (30s) - Add SARIF upload to GitHub Security tab for dashboard visibility - Consolidate security scans: remove pip-audit/npm audit from CI - Add .trivyignore for scan optimization - Set exit-code: 0 for hackathon-friendly non-blocking scans Benefits: - 90% faster scan time - Centralized Security tab (like Dependabot) - No Issue noise from daily scans - Better UX with console table + persistent dashboard
1 parent 6a182db commit bbdbadd

File tree

4 files changed

+78
-124
lines changed

4 files changed

+78
-124
lines changed

.github/workflows/backend.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,8 @@ jobs:
4646
- name: Run Lint (Ruff)
4747
run: poetry run ruff check .
4848

49-
# Decision: Lightweight security check with pip-audit (pinned in pyproject.toml)
50-
# Reason: Fast vulnerability check (seconds) without blocking PR
51-
- name: Security Scan (pip-audit)
52-
run: poetry run pip-audit --require-hashes=false || echo "Vulnerabilities found, see Dependabot for details"
53-
continue-on-error: true
49+
# Note: Security scanning moved to dedicated security.yml workflow (Trivy)
50+
# Reason: Centralized security checks with GitHub Code Scanning integration
5451

5552
# Decision: Run Pytest even if no tests exist yet (ensure setup works)
5653
# Reason: Validates that the test runner environment is correctly configured.

.github/workflows/frontend.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,8 @@ jobs:
4646
- name: Run Lint
4747
run: npm run lint
4848

49-
# Decision: Lightweight security check with npm audit (built-in tool)
50-
# Reason: Fast vulnerability check (seconds) without blocking PR
51-
- name: Security Scan (npm audit)
52-
run: npm audit --audit-level=critical || echo "Vulnerabilities found, see Dependabot for details"
53-
continue-on-error: true
49+
# Note: Security scanning moved to dedicated security.yml workflow (Trivy)
50+
# Reason: Centralized security checks with GitHub Code Scanning integration
5451

5552
- name: Run Build
5653
# This checks for type errors and build capability

.github/workflows/security.yml

Lines changed: 55 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,76 @@
1-
name: Security Gatekeeper (Weekly)
1+
name: Security Scan (Dashboard & Log)
22

3-
# Decision: Run heavy scans daily during hackathon, not on PR
4-
# Reason: Syft+Grype takes 3-5min; use Dependabot+built-in tools for PR checks
5-
# Hackathon ends 2026-02-21, so daily scan ensures coverage throughout the event
3+
# Decision: Use Trivy + GitHub Code Scanning for lightweight, dashboard-integrated security
4+
# Reason: Hackathon-friendly (non-blocking, fast), better UX than Issue accumulation
65
on:
6+
push:
7+
branches: ["main", "develop"]
8+
pull_request:
9+
branches: ["main", "develop"]
710
schedule:
8-
# Daily at 3:00 AM JST (18:00 UTC previous day) - Review results each morning
11+
# Daily at 3:00 AM JST for comprehensive scan
912
- cron: "0 18 * * *"
10-
workflow_dispatch: # Allow manual trigger anytime
11-
push:
12-
branches: ["main"]
13-
paths:
14-
- ".grype.yaml"
15-
- ".github/workflows/security.yml"
13+
workflow_dispatch:
1614

1715
permissions:
1816
contents: read
19-
issues: write # For creating issues on vulnerability detection
17+
security-events: write # Required for uploading to Security tab
2018

2119
jobs:
22-
security-check:
23-
name: Deep Supply Chain & Secret Scan
20+
trivy-scan:
21+
name: Trivy Security Scan
2422
runs-on: ubuntu-latest
25-
timeout-minutes: 10
23+
timeout-minutes: 5
2624

2725
steps:
2826
- name: Checkout code
2927
uses: actions/checkout@v4
30-
with:
31-
fetch-depth: 0 # Full history for TruffleHog
32-
33-
# 1. Secret Scanning (TruffleHog)
34-
# Decision: Full repository scan for scheduled runs (not diff-based)
35-
# Reason: Scheduled scans should audit entire codebase to prevent blind spots
36-
- name: Secret Scan
37-
id: trufflehog
38-
uses: trufflesecurity/trufflehog@v3.82.13
39-
with:
40-
path: ./
41-
# Note: No base/head specified = full repository scan
42-
extra_args: --only-verified
43-
continue-on-error: true
4428

45-
# 2. SBOM Generation (Syft)
46-
- name: Generate SBOM
47-
uses: anchore/sbom-action@v0.17.9
29+
# 1. Console output for immediate feedback in CI logs
30+
- name: Run Trivy (Log Output)
31+
uses: aquasecurity/trivy-action@0.28.0
4832
with:
49-
path: .
50-
format: spdx-json
51-
output-file: sbom.spdx.json
52-
53-
# 3. Vulnerability Scan (Grype)
54-
# Decision: Fail on vulnerabilities but don't stop workflow (create issue instead)
55-
# Reason: Need actual failure signal to trigger issue creation
56-
- name: Vulnerability Scan
57-
id: grype
58-
uses: anchore/scan-action@v5.1.0
33+
scan-type: "fs"
34+
scan-ref: "."
35+
format: "table"
36+
exit-code: "0" # Don't fail CI (hackathon-friendly)
37+
severity: "CRITICAL,HIGH"
38+
trivyignores: ".trivyignore"
39+
40+
# 2. SARIF output for GitHub Security tab integration
41+
- name: Run Trivy (SARIF Output)
42+
uses: aquasecurity/trivy-action@0.28.0
5943
with:
60-
sbom: sbom.spdx.json
61-
fail-build: true # Exit code 1 on vulnerabilities (enables detection)
62-
severity-cutoff: critical
63-
output-format: table
64-
continue-on-error: true # Don't stop workflow, proceed to issue creation
65-
66-
# 4. Create Issue on Vulnerability Detection
67-
# Decision: Avoid duplicate issues by checking for open security alerts
68-
# Reason: Daily scans would create noise if vulnerabilities persist
69-
- name: Create Security Issue
70-
if: steps.grype.outcome == 'failure' || steps.trufflehog.outcome == 'failure'
71-
uses: actions/github-script@v7
44+
scan-type: "fs"
45+
scan-ref: "."
46+
format: "sarif"
47+
output: "trivy-results.sarif"
48+
exit-code: "0" # Don't fail CI
49+
severity: "CRITICAL,HIGH"
50+
trivyignores: ".trivyignore"
51+
52+
# 3. Upload results to GitHub Security tab (visible like Dependabot alerts)
53+
- name: Upload Trivy scan results to GitHub Security tab
54+
uses: github/codeql-action/upload-sarif@v3
55+
if: always() # Upload even if scan found issues
7256
with:
73-
script: |
74-
const grypeFailure = '${{ steps.grype.outcome }}' === 'failure';
75-
const truffleFailure = '${{ steps.trufflehog.outcome }}' === 'failure';
76-
77-
// Fixed title for deduplication
78-
const title = '🔒 Security Alert: Automated Scan Results';
79-
80-
// Check for existing open issue
81-
const existingIssues = await github.rest.issues.listForRepo({
82-
owner: context.repo.owner,
83-
repo: context.repo.repo,
84-
state: 'open',
85-
labels: 'security-scan',
86-
per_page: 1
87-
});
88-
89-
const issues = [];
90-
if (grypeFailure) issues.push('Critical vulnerabilities in dependencies');
91-
if (truffleFailure) issues.push('Secrets detected in repository');
57+
sarif_file: "trivy-results.sarif"
58+
category: "trivy-fs-scan"
9259

93-
const body = `## Latest Scan: ${new Date().toISOString().split('T')[0]}
94-
95-
**Issues Detected**: ${issues.join(', ')}
96-
**Scan Date**: ${new Date().toISOString()}
97-
**Workflow Run**: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
98-
99-
### Detected Issues
100-
${grypeFailure ? '- ⚠️ **Critical vulnerabilities** in dependencies (see Grype logs)' : ''}
101-
${truffleFailure ? '- 🔑 **Secrets leaked** in repository (see TruffleHog logs)' : ''}
102-
103-
### Action Required
104-
1. Review the workflow logs for detailed information
105-
2. ${grypeFailure ? 'Update affected dependencies or add exceptions to `.grype.yaml` with justification' : ''}
106-
3. ${truffleFailure ? 'Remove secrets from repository and rotate compromised credentials immediately' : ''}
107-
4. Close this issue once resolved
60+
secret-scan:
61+
name: Secret Scanning
62+
runs-on: ubuntu-latest
63+
timeout-minutes: 5
10864

109-
### Notes
110-
- This is a daily automated scan during hackathon
111-
- PRs are checked with lightweight tools (pip-audit/npm audit)
112-
- Dependabot will create PRs for available updates
113-
`;
65+
steps:
66+
- name: Checkout code
67+
uses: actions/checkout@v4
68+
with:
69+
fetch-depth: 0
11470

115-
if (existingIssues.data.length > 0) {
116-
// Update existing issue
117-
const issueNumber = existingIssues.data[0].number;
118-
await github.rest.issues.createComment({
119-
owner: context.repo.owner,
120-
repo: context.repo.repo,
121-
issue_number: issueNumber,
122-
body: `---\n${body}`
123-
});
124-
console.log(`Updated existing issue #${issueNumber}`);
125-
} else {
126-
// Create new issue
127-
await github.rest.issues.create({
128-
owner: context.repo.owner,
129-
repo: context.repo.repo,
130-
title: title,
131-
body: body,
132-
labels: ['security-scan', 'dependencies']
133-
});
134-
console.log('Created new security issue');
135-
}
71+
- name: TruffleHog Secret Scan
72+
uses: trufflesecurity/trufflehog@v3.82.13
73+
with:
74+
path: ./
75+
extra_args: --only-verified
76+
continue-on-error: true

.trivyignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Trivy ignore patterns
2+
# Decision: Exclude paths that are not our code or cause noise
3+
# Reason: Focus on actual application vulnerabilities, not 3rd-party dependencies in node_modules
4+
5+
# Exclude node_modules (managed by Dependabot)
6+
**/node_modules/**
7+
8+
# Exclude Python virtual environments
9+
**/.venv/**
10+
**/venv/**
11+
12+
# Exclude build outputs
13+
**/dist/**
14+
**/build/**
15+
**/.next/**
16+
17+
# Exclude test fixtures
18+
**/tests/**/__fixtures__/**
19+
**/test/**/__fixtures__/**

0 commit comments

Comments
 (0)