Component: internal/output/vertical.go
Affects: --format=vertical output
Class: GitHub Actions workflow-command injection (incomplete fix of #2749 / PR #2750)
Background
PR #2750 sanitised source-file path strings in vertical.go to prevent \r/\n bytes reaching the GHA runner. Three fmt.Fprintf call sites in the same file were not covered:
| Function |
Unsanitized fields |
printVerticalVulnerabilitiesForPackages |
pkgSourceName, pkg.InstalledVersion |
printVerticalLicenseViolations |
pkg.Name, pkg.InstalledVersion |
printVerticalPkgDeprecatedSummary |
pkg.Name, pkg.InstalledVersion |
pkg.InstalledVersion and pkg.Name come from user-controlled lock files. A crafted lock file can encode a CR byte inside the version field using the standard JSON \r escape; Go's encoding/json decodes it before osv-scanner processes it. The raw byte then reaches stdout, and when the output is consumed by the GHA runner, it is treated as a workflow directive.
--format=table (default) is not affected — go-pretty strips control characters. --format=gh-annotations is not affected — it has explicit sanitisation from PR #2669.
Impact
An attacker with pull-request access (fork PR) can silence ::error::CVE-… annotations produced by osv-scanner by injecting ::stop-commands:: into a package version field in the lock file, making the scan appear clean to reviewers.
Fix
Apply SanitizeForWorkflowCommand to pkg.Name, pkgSourceName, and pkg.InstalledVersion at the three affected call sites. PR #2791 implements this fix.
I'm also filing this through the appropriate security channel (Google OSS-VRP) in parallel.
Component:
internal/output/vertical.goAffects:
--format=verticaloutputClass: GitHub Actions workflow-command injection (incomplete fix of #2749 / PR #2750)
Background
PR #2750 sanitised source-file path strings in
vertical.goto prevent\r/\nbytes reaching the GHA runner. Threefmt.Fprintfcall sites in the same file were not covered:printVerticalVulnerabilitiesForPackagespkgSourceName,pkg.InstalledVersionprintVerticalLicenseViolationspkg.Name,pkg.InstalledVersionprintVerticalPkgDeprecatedSummarypkg.Name,pkg.InstalledVersionpkg.InstalledVersionandpkg.Namecome from user-controlled lock files. A crafted lock file can encode a CR byte inside the version field using the standard JSON\rescape; Go'sencoding/jsondecodes it before osv-scanner processes it. The raw byte then reaches stdout, and when the output is consumed by the GHA runner, it is treated as a workflow directive.--format=table(default) is not affected —go-prettystrips control characters.--format=gh-annotationsis not affected — it has explicit sanitisation from PR #2669.Impact
An attacker with pull-request access (fork PR) can silence
::error::CVE-…annotations produced by osv-scanner by injecting::stop-commands::into a package version field in the lock file, making the scan appear clean to reviewers.Fix
Apply
SanitizeForWorkflowCommandtopkg.Name,pkgSourceName, andpkg.InstalledVersionat the three affected call sites. PR #2791 implements this fix.I'm also filing this through the appropriate security channel (Google OSS-VRP) in parallel.