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"
@ -24,17 +25,19 @@ type csvReporter struct {
}
type csvRecord struct {
ecosystem string
manifestPath string
packageName string
packageVersion string
introducedBy string
pathToRoot string
violationReason string
osvId string
cveId string
vulnSeverity string
vulnSummary string
ecosystem string
manifestPath string
packageName string
packageVersion string
introducedBy string
pathToRoot string
violationReason string
osvId string
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,14 +28,16 @@ const (
summaryWeightMediumVuln = 2
summaryWeightLowVuln = 1
summaryWeightUnpopular = 1
summaryWeightUsedInCode = 1
summaryWeightMajorDrift = 2
// Opinionated thresholds for identifying repo popularity by stars
minStarsForPopularity = 10
tagVuln = "vulnerability"
tagUnpopular = "low popularity"
tagDrift = "drift"
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
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
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