diff --git a/review-enrichment/src/analyzers/dependency-scan.ts b/review-enrichment/src/analyzers/dependency-scan.ts index 76e59bc3ea..2ccc15f400 100644 --- a/review-enrichment/src/analyzers/dependency-scan.ts +++ b/review-enrichment/src/analyzers/dependency-scan.ts @@ -49,7 +49,13 @@ const NPM_VERSION_PREFIX_RE = /^[\^~>=<\s]+/; // stopped at `[` silently dropped every pinned-with-extras dependency from the CVE scan. const PYPI_RE = /^([A-Za-z0-9._-]+)(?:\[[A-Za-z0-9._,\s-]+\])?\s*==\s*([0-9][^\s;]*)/; -const GO_RE = /^([a-z0-9.\/-]+)\s+v([0-9][^\s]*)/; +// Go module paths are case-sensitive and the element grammar admits A-Z plus the full +// punctuation set Go allows (`. _ ~ -`, per golang.org/x/mod/module modPathOK), not just `.`/`-`. +// A narrower class silently drops uppercase or `_`/`~` paths (github.com/BurntSushi/toml, +// github.com/foo_bar/baz, golang.org/x/~exp) from every dependency-fed scanner (CVE, license, +// provenance, native-build). The class stays strictly more permissive, so lowercase paths are +// unaffected, and the case-sensitive name is preserved verbatim for the OSV lookup. +const GO_RE = /^([A-Za-z0-9._~\/-]+)\s+v([0-9][^\s]*)/; function parseLine( manifest: string, diff --git a/review-enrichment/test/enrichment.test.ts b/review-enrichment/test/enrichment.test.ts index a65b85ab9b..4f7a8462fc 100644 --- a/review-enrichment/test/enrichment.test.ts +++ b/review-enrichment/test/enrichment.test.ts @@ -143,6 +143,20 @@ test("extractDependencyChanges: PyPI exact pins with PEP 508 extras are parsed u assert.equal(byPkg.celery.to, "5.4.0"); }); +test("extractDependencyChanges: Go paths with uppercase and `_`/`~` punctuation are parsed", () => { + // Go module paths are case-sensitive and admit the full `. _ ~ -` punctuation set; a narrower + // path class would silently drop these deps from the OSV scan. Names are preserved verbatim. + const changes = extractDependencyChanges([ + { path: "go.mod", patch: "+\tgithub.com/BurntSushi/toml v1.4.0" }, + { path: "go.mod", patch: "+\tgithub.com/foo_bar/baz v0.9.1" }, + { path: "go.mod", patch: "+\texample.com/x/~exp v1.0.0" }, + ]); + const byPkg = Object.fromEntries(changes.map((c) => [c.package, c])); + assert.equal(byPkg["github.com/BurntSushi/toml"].to, "1.4.0"); + assert.equal(byPkg["github.com/foo_bar/baz"].to, "0.9.1"); + assert.equal(byPkg["example.com/x/~exp"].to, "1.0.0"); +}); + test("queryOsv: maps vulns; severity from database_specific; fixedIn from affected; [] on non-ok", async () => { const cves = await queryOsv( "npm",