Skip to content

Commit 5dd84e9

Browse files
committed
chore: reset to main
1 parent 8a87765 commit 5dd84e9

File tree

15 files changed

+668
-2292
lines changed

15 files changed

+668
-2292
lines changed

.snyk

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ ignore:
66
- 'snyk-nodejs-lockfile-parser > @yarnpkg/core > tar':
77
reason: 'Indirect dependency from snyk-nodejs-lockfile-parser, waiting for upstream fix'
88
expires: 2026-03-26T00:00:00.000Z
9+
SNYK-JS-TAR-15416075:
10+
- 'snyk-nodejs-lockfile-parser > @yarnpkg/core > tar':
11+
reason: 'Indirect dependency from snyk-nodejs-lockfile-parser, waiting for upstream fix'
12+
expires: 2026-03-26T00:00:00.000Z
13+
SNYK-JS-TAR-15456201:
14+
- 'snyk-nodejs-lockfile-parser > @yarnpkg/core > tar':
15+
reason: 'Indirect dependency from snyk-nodejs-lockfile-parser, waiting for upstream fix'
16+
expires: 2026-03-26T00:00:00.000Z
917
patch: {}

lib/analyzer/applications/java.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ async function unpackJars(
251251
return fingerprints;
252252
}
253253

254+
/**
255+
* Packages with inaccurate pom.properties files return null so that the JAR
256+
* will be resolved using the SHA lookup instead.
257+
*
258+
* Long-term solution: resolve all JARs via maven-deps to remove the need for overrides.
259+
*/
260+
const POM_PROPERTIES_OVERRIDES = new Set([
261+
"com.microsoft.sqlserver:mssql-jdbc",
262+
]);
263+
254264
/**
255265
* Gets coords from the contents of a pom.properties file
256266
* @param {string} fileContent
@@ -261,6 +271,10 @@ export function getCoordsFromPomProperties(
261271
): JarCoords | null {
262272
const coords = parsePomProperties(fileContent);
263273

274+
if (POM_PROPERTIES_OVERRIDES.has(`${coords.groupId}:${coords.artifactId}`)) {
275+
return null;
276+
}
277+
264278
// we need all of these props to allow us to inject the package
265279
// into the depGraph
266280
if (!coords.artifactId || !coords.groupId || !coords.version) {

lib/go-parser/go-binary.ts

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ const debug = Debug("snyk");
4444
export class GoBinary {
4545
public name: string;
4646
public modules: GoModule[];
47+
public goVersion: string;
4748
private hasPclnTab: boolean;
4849

4950
constructor(goElfBinary: Elf) {
50-
[this.name, this.modules] = extractModuleInformation(goElfBinary);
51+
[this.name, this.modules, this.goVersion] =
52+
extractModuleInformation(goElfBinary);
5153

5254
const pclnTab = goElfBinary.body.sections.find(
5355
(section) => section.name === ".gopclntab",
@@ -108,6 +110,19 @@ export class GoBinary {
108110
// else: pclnTab exists but module has no packages - don't report anything
109111
}
110112

113+
if (this.goVersion) {
114+
const stdlibNodeId = `stdlib@${this.goVersion}`;
115+
goModulesDepGraph.addPkgNode(
116+
{ name: "stdlib", version: this.goVersion },
117+
stdlibNodeId,
118+
);
119+
goModulesDepGraph.connectDep(goModulesDepGraph.rootNodeId, stdlibNodeId);
120+
} else {
121+
debug(
122+
`Skipping stdlib node for ${this.name}: could not parse Go version`,
123+
);
124+
}
125+
111126
return goModulesDepGraph.build();
112127
}
113128

@@ -184,15 +199,36 @@ interface GoFileNameError extends Error {
184199
moduleName: string;
185200
}
186201

202+
/**
203+
* Strips the "go" prefix from a Go version string and validates the format.
204+
* Returns the cleaned version (e.g., "1.21.0") or empty string if invalid.
205+
* Rejects RC/beta/devel versions since we cannot accurately match vulnerabilities
206+
* against pre-release builds.
207+
*/
208+
export function parseGoVersion(rawVersion: string): string {
209+
// Only match release versions (e.g., "go1.21" or "go1.21.5").
210+
// Reject RC/beta (go1.21rc1, go1.22beta2) and devel builds.
211+
const match = rawVersion.match(/^go(\d+\.\d+(?:\.\d+)?)$/);
212+
if (!match) {
213+
return "";
214+
}
215+
const ver = match[1];
216+
// Ensure three-segment semver (e.g., "1.19" → "1.19.0") because
217+
// @snyk/vuln uses node's semver library which requires three segments.
218+
return ver.includes(".", ver.indexOf(".") + 1) ? ver : ver + ".0";
219+
}
220+
187221
export function extractModuleInformation(
188222
binary: Elf,
189-
): [name: string, deps: GoModule[]] {
190-
const mod = readRawBuildInfo(binary);
191-
if (!mod) {
223+
): [name: string, deps: GoModule[], goVersion: string] {
224+
const { goVersion: rawGoVersion, modInfo } = readRawBuildInfo(binary);
225+
if (!modInfo) {
192226
throw Error("binary contains empty module info");
193227
}
194228

195-
const [pathDirective, mainModuleLine, ...versionsLines] = mod
229+
const goVersion = parseGoVersion(rawGoVersion);
230+
231+
const [pathDirective, mainModuleLine, ...versionsLines] = modInfo
196232
.replace("\r", "")
197233
.split("\n");
198234
const lineSplit = mainModuleLine.split("\t");
@@ -224,7 +260,7 @@ export function extractModuleInformation(
224260
}
225261
});
226262

227-
return [name, modules];
263+
return [name, modules, goVersion];
228264
}
229265

230266
// Source
@@ -234,7 +270,12 @@ export function extractModuleInformation(
234270
* module version information in the executable binary
235271
* @param binary
236272
*/
237-
export function readRawBuildInfo(binary: Elf): string {
273+
export interface RawBuildInfo {
274+
goVersion: string;
275+
modInfo: string;
276+
}
277+
278+
export function readRawBuildInfo(binary: Elf): RawBuildInfo {
238279
const buildInfoMagic = "\xff Go buildinf:";
239280
// Read the first 64kB of dataAddr to find the build info blob.
240281
// On some platforms, the blob will be in its own section, and DataStart
@@ -272,9 +313,9 @@ export function readRawBuildInfo(binary: Elf): string {
272313
const ptrSize = data[14];
273314
if ((data[15] & 2) !== 0) {
274315
data = data.subarray(32);
275-
[, data] = decodeString(data);
276-
const [mod] = decodeString(data);
277-
return mod;
316+
const [goVersion, rest] = decodeString(data);
317+
const [mod] = decodeString(rest);
318+
return { goVersion, modInfo: mod };
278319
} else {
279320
const bigEndian = data[15] !== 0;
280321

@@ -326,7 +367,7 @@ export function readRawBuildInfo(binary: Elf): string {
326367
// First 16 bytes are unicodes as last 16
327368
// Mirrors go version source code
328369
if (mod.length >= 33 && mod[mod.length - 17] === "\n") {
329-
return mod.slice(16, mod.length - 16);
370+
return { goVersion: version, modInfo: mod.slice(16, mod.length - 16) };
330371
} else {
331372
throw Error("binary is not built with go module support");
332373
}

0 commit comments

Comments
 (0)