Added usage evidence in summary and CSV report (#341)

* Added used in code tag for usage evidences in summary report

Signed-off-by: Omkar Phansopkar <omkarphansopkar@gmail.com>

* Added usage evidence in csv report

Signed-off-by: Omkar Phansopkar <omkarphansopkar@gmail.com>

* temporary e2e test for csv report

Signed-off-by: Omkar Phansopkar <omkarphansopkar@gmail.com>

* Fixed E2E test for csv report comparison

Signed-off-by: Omkar Phansopkar <omkarphansopkar@gmail.com>

---------

Signed-off-by: Omkar Phansopkar <omkarphansopkar@gmail.com>
This commit is contained in:
Omkar Phansopkar 2025-02-06 06:17:18 +05:30 committed by GitHub
parent 89a6233e76
commit 1e9fae0330
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 94 additions and 17 deletions

View File

@ -3,6 +3,7 @@ package reporter
import (
"encoding/csv"
"os"
"strconv"
"strings"
"github.com/safedep/dry/utils"
@ -35,6 +36,8 @@ type csvRecord struct {
cveId string
vulnSeverity string
vulnSummary string
usageEvidenceCount string
usageEvidenceSample string
}
func NewCsvReporter(config CsvReportingConfig) (Reporter, error) {
@ -145,11 +148,22 @@ func (r *csvReporter) Finish() error {
}
}
usageEvidenceCount := ""
usageEvidenceSample := ""
if v.Package.CodeAnalysis != nil && v.Package.CodeAnalysis.UsageEvidences != nil {
usageEvidenceCount = strconv.Itoa(len(v.Package.CodeAnalysis.UsageEvidences))
if len(v.Package.CodeAnalysis.UsageEvidences) > 0 {
usageEvidenceSample = v.Package.CodeAnalysis.UsageEvidences[0].UsageFilePath + ":" + strconv.Itoa(int(v.Package.CodeAnalysis.UsageEvidences[0].Line))
}
}
newRecord := record
newRecord.osvId = vulnId
newRecord.cveId = cveId
newRecord.vulnSummary = summary
newRecord.vulnSeverity = risk
newRecord.usageEvidenceCount = usageEvidenceCount
newRecord.usageEvidenceSample = usageEvidenceSample
records = append(records, newRecord)
}
@ -174,7 +188,8 @@ func (r *csvReporter) persistCsvRecords(records []csvRecord) error {
w := csv.NewWriter(f)
defer w.Flush()
err = w.Write([]string{"Ecosystem",
err = w.Write([]string{
"Ecosystem",
"Manifest Path",
"Package Name",
"Package Version",
@ -185,6 +200,8 @@ func (r *csvReporter) persistCsvRecords(records []csvRecord) error {
"CVE ID",
"Vulnerability Severity",
"Vulnerability Summary",
"Usage Evidence count",
"Sample Usage Evidence",
})
if err != nil {
return err
@ -201,6 +218,8 @@ func (r *csvReporter) persistCsvRecords(records []csvRecord) error {
csvRecord.cveId,
csvRecord.vulnSeverity,
csvRecord.vulnSummary,
csvRecord.usageEvidenceCount,
csvRecord.usageEvidenceSample,
}); err != nil {
return err
}

View File

@ -28,6 +28,7 @@ const (
summaryWeightMediumVuln = 2
summaryWeightLowVuln = 1
summaryWeightUnpopular = 1
summaryWeightUsedInCode = 1
summaryWeightMajorDrift = 2
// Opinionated thresholds for identifying repo popularity by stars
@ -36,6 +37,7 @@ const (
tagVuln = "vulnerability"
tagUnpopular = "low popularity"
tagDrift = "drift"
tagUsedInCode = "used-in-code"
summaryReportMaxUpgradeAdvice = 5
)
@ -272,6 +274,7 @@ func (r *summaryReporter) processForDepsUsageEvidence(pkg *models.Package) {
r.summary.codeanalysis.unknown += 1
} else if len(pkg.CodeAnalysis.UsageEvidences) > 0 {
r.summary.codeanalysis.used += 1
r.addPkgForRemediationAdvice(pkg, summaryWeightUsedInCode, tagUsedInCode)
}
}

View File

@ -20,3 +20,4 @@ bash $E2E_THIS_DIR/scenario-7-rubygems-project-url.sh
bash $E2E_THIS_DIR/scenario-8-summary-report.sh
bash $E2E_THIS_DIR/scenario-9-malware-analysis.sh
bash $E2E_THIS_DIR/scenario-10-code-scan.sh
bash $E2E_THIS_DIR/scenario-11-code-csvreport.sh

View File

@ -0,0 +1,3 @@
pandas>=1.1
flask>=1.0.4
langchain>=0.2.1

View File

@ -1,3 +1,5 @@
import plib as pl
import pandas as pd
from flask import Flask, request
app = Flask(__name__)
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})

View File

@ -0,0 +1,49 @@
#!/bin/bash
set -x
E2E_CODEPATH=$(realpath $E2E_FIXTURES/code)
E2E_VET_CODE_DB="/tmp/vet-code.db"
E2E_VET_CSV_REPORT="/tmp/vet-code.csv"
E2E_VET_EXPECTED_CSV="/tmp/expected-report.csv"
rm -f $E2E_VET_CODE_DB
rm -f $E2E_VET_CSV_REPORT
rm -f $E2E_VET_EXPECTED_CSV
$E2E_VET_CODE_SCAN_CMD \
--app $E2E_CODEPATH \
--db $E2E_VET_CODE_DB \
--lang python || exit 1
ls $E2E_VET_CODE_DB || exit 1
$E2E_VET_BINARY scan \
-D $E2E_CODEPATH \
--code $E2E_VET_CODE_DB \
--filter 'vulns.critical.exists(p, true) || vulns.high.exists(p, true)' \
--report-csv $E2E_VET_CSV_REPORT || exit 1
ls $E2E_VET_CSV_REPORT || exit 1
cat > $E2E_VET_EXPECTED_CSV << EOL
Ecosystem,Manifest Path,Package Name,Package Version,Violation,Introduced By,Path To Root,OSV ID,CVE ID,Vulnerability Severity,Vulnerability Summary,Usage Evidence count,Sample Usage Evidence
PyPI,$E2E_CODEPATH/requirements.txt,flask,1.0.4,cli-filter,flask,flask,GHSA-m2qf-hxjv-5gpq,CVE-2023-30861,HIGH,Flask vulnerable to possible disclosure of permanent session cookie due to missing Vary: Cookie header,1,$E2E_CODEPATH/usage.py:4
PyPI,$E2E_CODEPATH/requirements.txt,flask,1.0.4,cli-filter,flask,flask,PYSEC-2023-62,CVE-2023-30861,,,1,$E2E_CODEPATH/usage.py:4
PyPI,$E2E_CODEPATH/requirements.txt,langchain,0.2.1,cli-filter,langchain,langchain,GHSA-3hjh-jh2h-vrg6,CVE-2024-2965,MEDIUM,Denial of service in langchain-community,0,
PyPI,$E2E_CODEPATH/requirements.txt,langchain,0.2.1,cli-filter,langchain,langchain,PYSEC-2024-114,CVE-2024-7042,CRITICAL,,0,
PyPI,$E2E_CODEPATH/requirements.txt,langchain,0.2.1,cli-filter,langchain,langchain,PYSEC-2024-118,CVE-2024-2965,MEDIUM,,0,
EOL
# Compare CSV heading
head -n 1 "$E2E_VET_EXPECTED_CSV" | diff - <(head -n 1 "$E2E_VET_CSV_REPORT") || exit 1
# Compare Sorted CSV body
diff <(tail -n +2 "$E2E_VET_EXPECTED_CSV" | sort) <(tail -n +2 "$E2E_VET_CSV_REPORT" | sort) || exit 1
rm -f $E2E_VET_CODE_DB
rm -f $E2E_VET_CSV_REPORT
rm -f $E2E_VET_EXPECTED_CSV
exit 0