mirror of
https://github.com/imjasonh/govulncheck-action
synced 2026-07-18 22:56:04 +00:00
Add vulnerable example and enhance action features
This commit adds a comprehensive example demonstrating the govulncheck action's capabilities, along with several enhancements to improve the user experience. ## Changes ### Example Setup - Added example/main.go that uses golang.org/x/net v0.0.0-20220906165146-f3363e06e74c (vulnerable version) - Example intentionally calls html.Parse to trigger vulnerability detection - Demonstrates how the action creates annotations on vulnerable code ### Enhanced Annotations - Fixed file path handling when running in subdirectories (e.g., './example') - Added rich context to annotations including: - Vulnerability summaries and CVE numbers - Direct links to Go vulnerability database (pkg.go.dev/vuln) - Fixed version information - Clear indication of which function is vulnerable (e.g., "html.Parse" not "main") - Sorted vulnerabilities by OSV ID for consistent display ### Suggested Fixes - When vulnerable code is actually called, creates notice annotations on go.mod - Shows current vs suggested dependency versions - Lists which specific vulnerabilities have active call sites - Provides actionable upgrade recommendations ### Workflow Summary - Added comprehensive workflow summary using GitHub Actions summary API - Displays vulnerabilities in formatted tables by module - Shows vulnerable code locations organized by file - Includes links to Go vulnerability database entries - Provides clear recommendations for fixing vulnerabilities ### Bug Fixes - Fixed JSON parsing to handle both JSON lines and multi-line JSON formats - Fixed annotation file paths to be relative to repository root - Improved vulnerability function name extraction from trace data - Enhanced OSV detail parsing and storage ## Testing The example workflow demonstrates all features by intentionally using a vulnerable dependency. When run, it will: 1. Detect vulnerabilities in golang.org/x/net 2. Create warning annotations on go.mod and main.go 3. Suggest specific version updates 4. Generate a detailed workflow summary This provides a complete demonstration of the action's vulnerability detection and reporting capabilities.
This commit is contained in:
parent
f6e59d4d11
commit
3a117d24f8
9 changed files with 776 additions and 67 deletions
|
|
@ -1,6 +1,7 @@
|
|||
class VulnerabilityParser {
|
||||
parse(output) {
|
||||
const vulnerabilities = [];
|
||||
const osvDetails = {};
|
||||
|
||||
// Try to parse as JSON Lines first (one JSON object per line)
|
||||
const lines = output.split('\n').filter(line => line.trim());
|
||||
|
|
@ -22,7 +23,10 @@ class VulnerabilityParser {
|
|||
for (const line of lines) {
|
||||
try {
|
||||
const json = JSON.parse(line);
|
||||
if (json.finding) {
|
||||
if (json.osv) {
|
||||
// Store OSV details
|
||||
osvDetails[json.osv.id] = json.osv;
|
||||
} else if (json.finding) {
|
||||
console.log(`Found vulnerability: ${JSON.stringify(json.finding.osv || json.finding)}`);
|
||||
vulnerabilities.push(json);
|
||||
}
|
||||
|
|
@ -39,7 +43,10 @@ class VulnerabilityParser {
|
|||
for (const jsonStr of jsonObjects) {
|
||||
try {
|
||||
const json = JSON.parse(jsonStr);
|
||||
if (json.finding) {
|
||||
if (json.osv) {
|
||||
// Store OSV details
|
||||
osvDetails[json.osv.id] = json.osv;
|
||||
} else if (json.finding) {
|
||||
console.log(`Found vulnerability: ${JSON.stringify(json.finding.osv || json.finding)}`);
|
||||
vulnerabilities.push(json);
|
||||
}
|
||||
|
|
@ -49,6 +56,13 @@ class VulnerabilityParser {
|
|||
}
|
||||
}
|
||||
|
||||
// Attach OSV details to vulnerabilities
|
||||
for (const vuln of vulnerabilities) {
|
||||
if (vuln.finding.osv && osvDetails[vuln.finding.osv]) {
|
||||
vuln.osvDetails = osvDetails[vuln.finding.osv];
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Parsed ${vulnerabilities.length} vulnerabilities`);
|
||||
return vulnerabilities;
|
||||
}
|
||||
|
|
@ -71,14 +85,23 @@ class VulnerabilityParser {
|
|||
|
||||
for (const vuln of vulnerabilities) {
|
||||
const finding = vuln.finding;
|
||||
if (finding.trace) {
|
||||
for (const frame of finding.trace) {
|
||||
if (frame.position && frame.position.filename) {
|
||||
if (finding.trace && finding.trace.length > 0) {
|
||||
// The first frame in the trace is the vulnerable function
|
||||
const vulnerableFunction = finding.trace[0].function || 'unknown function';
|
||||
|
||||
// Look for frames that represent our code (not the vulnerable library)
|
||||
for (let i = 1; i < finding.trace.length; i++) {
|
||||
const frame = finding.trace[i];
|
||||
if (frame.position && frame.position.filename && !frame.position.filename.includes('/')) {
|
||||
// This frame is in our code (doesn't have path separators like library code)
|
||||
callSites.push({
|
||||
filename: frame.position.filename,
|
||||
line: frame.position.line || 1,
|
||||
function: frame.function || 'unknown function',
|
||||
osv: finding.osv || null
|
||||
vulnerableFunction: vulnerableFunction,
|
||||
osv: finding.osv || null,
|
||||
osvDetails: vuln.osvDetails || null,
|
||||
fixedVersion: finding.fixed_version || null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue