snyk 1.998.0 → 1.999.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/545.index.js +373 -352
- package/dist/cli/545.index.js.map +1 -1
- package/dist/cli/thirdPartyNotice.json +2 -2
- package/package.json +1 -1
package/dist/cli/545.index.js
CHANGED
|
@@ -159237,18 +159237,381 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
159237
159237
|
|
|
159238
159238
|
/***/ }),
|
|
159239
159239
|
|
|
159240
|
+
/***/ 6803:
|
|
159241
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
159242
|
+
|
|
159243
|
+
"use strict";
|
|
159244
|
+
|
|
159245
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159246
|
+
exports.readRawBuildInfo = exports.extractModuleInformation = exports.GoBinary = void 0;
|
|
159247
|
+
const depGraph = __webpack_require__(26326);
|
|
159248
|
+
const event_loop_spinner_1 = __webpack_require__(77158);
|
|
159249
|
+
const path = __webpack_require__(85622);
|
|
159250
|
+
const varint = __webpack_require__(94676);
|
|
159251
|
+
const _1 = __webpack_require__(5998);
|
|
159252
|
+
const go_module_1 = __webpack_require__(79160);
|
|
159253
|
+
const pclntab_1 = __webpack_require__(77162);
|
|
159254
|
+
class GoBinary {
|
|
159255
|
+
constructor(goElfBinary) {
|
|
159256
|
+
[this.name, this.modules] = extractModuleInformation(goElfBinary);
|
|
159257
|
+
const pclnTab = goElfBinary.body.sections.find((section) => section.name === ".gopclntab");
|
|
159258
|
+
if (pclnTab === undefined) {
|
|
159259
|
+
throw Error("no pcln table found in Go binary");
|
|
159260
|
+
}
|
|
159261
|
+
this.matchFilesToModules(new pclntab_1.LineTable(pclnTab.data).go12MapFiles());
|
|
159262
|
+
}
|
|
159263
|
+
async depGraph() {
|
|
159264
|
+
const goModulesDepGraph = new depGraph.DepGraphBuilder({ name: _1.DEP_GRAPH_TYPE }, { name: this.name });
|
|
159265
|
+
for (const module of this.modules) {
|
|
159266
|
+
for (const pkg of module.packages) {
|
|
159267
|
+
if (event_loop_spinner_1.eventLoopSpinner.isStarving()) {
|
|
159268
|
+
await event_loop_spinner_1.eventLoopSpinner.spin();
|
|
159269
|
+
}
|
|
159270
|
+
const version = module.snykNormalisedVersion();
|
|
159271
|
+
const nodeId = `${pkg}@${version}`;
|
|
159272
|
+
goModulesDepGraph.addPkgNode({ name: pkg, version }, nodeId);
|
|
159273
|
+
goModulesDepGraph.connectDep(goModulesDepGraph.rootNodeId, nodeId);
|
|
159274
|
+
}
|
|
159275
|
+
}
|
|
159276
|
+
return goModulesDepGraph.build();
|
|
159277
|
+
}
|
|
159278
|
+
// matchFilesToModules goes through all files, extracts the package name and
|
|
159279
|
+
// adds it to the relevant module in the GoBinary.
|
|
159280
|
+
matchFilesToModules(files) {
|
|
159281
|
+
// goModCachePath is the path at which the modules are downloaded to. When
|
|
159282
|
+
// building a Go binary, this is usually either $GOMODCACHE or
|
|
159283
|
+
// $GOROOT/pkg/mod. Binaries built with `-trimpath` will have that module
|
|
159284
|
+
// cache path trimmed away, meaning that the goModCachePath will always be
|
|
159285
|
+
// empty.
|
|
159286
|
+
let goModCachePath = "";
|
|
159287
|
+
let moduleName = (mod) => {
|
|
159288
|
+
return mod.fullName();
|
|
159289
|
+
};
|
|
159290
|
+
for (const fileName of files) {
|
|
159291
|
+
if (fileName === "<autogenerated>") {
|
|
159292
|
+
continue;
|
|
159293
|
+
}
|
|
159294
|
+
// As long as the goModCachePath is not set, try finding it. We do not
|
|
159295
|
+
// have a way of knowing whether we're checking a `-trimpath` binary, so
|
|
159296
|
+
// for `-trimpath` binaries we will be wasting a couple of cycles by
|
|
159297
|
+
// trying to find the goModCachePath for every file.
|
|
159298
|
+
if (goModCachePath === "") {
|
|
159299
|
+
[goModCachePath, moduleName] = this.determineModuleCachePath(fileName);
|
|
159300
|
+
}
|
|
159301
|
+
// Assuming that goModCachePath is set, this is true for files outside the
|
|
159302
|
+
// modPath, which is usually the developers files (the built module) and
|
|
159303
|
+
// Go source files (stdlib, runtime etc). If it is not set, this check is
|
|
159304
|
+
// meaningless.
|
|
159305
|
+
if (!fileName.startsWith(goModCachePath)) {
|
|
159306
|
+
continue;
|
|
159307
|
+
}
|
|
159308
|
+
// remove the go module cache path at the beginning of the file name,
|
|
159309
|
+
// leaving only the module + file paths.
|
|
159310
|
+
const pkgFile = fileName.slice(goModCachePath.length);
|
|
159311
|
+
// Try to find the module that matches our file name, and if found,
|
|
159312
|
+
// extract the package name out of it.
|
|
159313
|
+
// Go source files will not be matched by any module, so they will be
|
|
159314
|
+
// skipped automatically.
|
|
159315
|
+
for (const module of this.modules) {
|
|
159316
|
+
const modFullName = moduleName(module);
|
|
159317
|
+
if (pkgFile.startsWith(modFullName)) {
|
|
159318
|
+
// For example, the filename "github.com/my/pkg@v0.0.1/a/a.go" will be
|
|
159319
|
+
// split into "github.com/my/pkg@v0.0.1/" and "a/a.go". We then get
|
|
159320
|
+
// the package name from the package and file section, and add the
|
|
159321
|
+
// normalized module name (without the version) in front. This will
|
|
159322
|
+
// result in the package name "github.com/my/pkg/a".
|
|
159323
|
+
const parts = pkgFile.split(modFullName);
|
|
159324
|
+
if (parts.length !== 2 || parts[0] !== "") {
|
|
159325
|
+
throw {
|
|
159326
|
+
fileName: pkgFile,
|
|
159327
|
+
moduleName: modFullName,
|
|
159328
|
+
};
|
|
159329
|
+
}
|
|
159330
|
+
// for files in the "root" of a module
|
|
159331
|
+
// (github.com/my/pkg@v0.0.1/a.go), the path.parse expression returns
|
|
159332
|
+
// just a slash. This would result in a package name with a trailing
|
|
159333
|
+
// slash, which is incorrect.
|
|
159334
|
+
let dirName = path.parse(parts[1]).dir;
|
|
159335
|
+
if (dirName === "/") {
|
|
159336
|
+
dirName = "";
|
|
159337
|
+
}
|
|
159338
|
+
const pkgName = module.name + dirName;
|
|
159339
|
+
if (!module.packages.includes(pkgName)) {
|
|
159340
|
+
module.packages.push(pkgName);
|
|
159341
|
+
}
|
|
159342
|
+
}
|
|
159343
|
+
}
|
|
159344
|
+
}
|
|
159345
|
+
}
|
|
159346
|
+
determineModuleCachePath(fileName) {
|
|
159347
|
+
// this is the module name as it appears in the directory on *non-vendored*
|
|
159348
|
+
// dependencies, e.g. "/go/pkg/mod/github.com/my/repo@v1.0.0".
|
|
159349
|
+
const fullName = (m) => {
|
|
159350
|
+
return m.fullName();
|
|
159351
|
+
};
|
|
159352
|
+
for (const [, mod] of Object.entries(this.modules)) {
|
|
159353
|
+
if (!fileName.includes(mod.name)) {
|
|
159354
|
+
continue;
|
|
159355
|
+
}
|
|
159356
|
+
const parts = fileName.split(fullName(mod));
|
|
159357
|
+
if (parts.length === 2) {
|
|
159358
|
+
return [parts[0], fullName];
|
|
159359
|
+
}
|
|
159360
|
+
else {
|
|
159361
|
+
const parts = fileName.split(path.join("vendor", mod.name));
|
|
159362
|
+
if (parts.length === 2) {
|
|
159363
|
+
return [
|
|
159364
|
+
// trailing slash is important to properly separate module name from
|
|
159365
|
+
// directory. parts[0] would always include it, so we also need to
|
|
159366
|
+
// add it to "vendor".
|
|
159367
|
+
path.join(parts[0], "vendor/"),
|
|
159368
|
+
// for vendored modules, the directory does not contain the version,
|
|
159369
|
+
// e.g. /app/vendor/github.com/my/repo/. As such, the "full name" of
|
|
159370
|
+
// the module should also not contain the version string.
|
|
159371
|
+
(m) => {
|
|
159372
|
+
return m.name;
|
|
159373
|
+
},
|
|
159374
|
+
];
|
|
159375
|
+
}
|
|
159376
|
+
}
|
|
159377
|
+
}
|
|
159378
|
+
return ["", fullName];
|
|
159379
|
+
}
|
|
159380
|
+
}
|
|
159381
|
+
exports.GoBinary = GoBinary;
|
|
159382
|
+
function extractModuleInformation(binary) {
|
|
159383
|
+
const mod = readRawBuildInfo(binary);
|
|
159384
|
+
if (!mod) {
|
|
159385
|
+
throw Error("binary contains empty module info");
|
|
159386
|
+
}
|
|
159387
|
+
const [, mainModuleLine, ...versionsLines] = mod.split("\n");
|
|
159388
|
+
const [, name] = mainModuleLine.split("\t");
|
|
159389
|
+
const modules = [];
|
|
159390
|
+
versionsLines.forEach((versionLine) => {
|
|
159391
|
+
const [, name, ver] = versionLine.split("\t");
|
|
159392
|
+
if (!name || !ver) {
|
|
159393
|
+
return;
|
|
159394
|
+
}
|
|
159395
|
+
modules.push(new go_module_1.GoModule(name, ver));
|
|
159396
|
+
});
|
|
159397
|
+
return [name, modules];
|
|
159398
|
+
}
|
|
159399
|
+
exports.extractModuleInformation = extractModuleInformation;
|
|
159400
|
+
// Source
|
|
159401
|
+
// https://cs.opensource.google/go/go/+/refs/tags/go1.18.5:src/debug/buildinfo/buildinfo.go;l=142
|
|
159402
|
+
/**
|
|
159403
|
+
* Function finds and returns the Go version and
|
|
159404
|
+
* module version information in the executable binary
|
|
159405
|
+
* @param binary
|
|
159406
|
+
*/
|
|
159407
|
+
function readRawBuildInfo(binary) {
|
|
159408
|
+
const buildInfoMagic = "\xff Go buildinf:";
|
|
159409
|
+
// Read the first 64kB of dataAddr to find the build info blob.
|
|
159410
|
+
// On some platforms, the blob will be in its own section, and DataStart
|
|
159411
|
+
// returns the address of that section. On others, it's somewhere in the
|
|
159412
|
+
// data segment; the linker puts it near the beginning.
|
|
159413
|
+
const dataAddr = dataStart(binary);
|
|
159414
|
+
let data = readData(binary.body.programs, dataAddr, 64 * 1024) || Buffer.from([]);
|
|
159415
|
+
const buildInfoAlign = 16;
|
|
159416
|
+
const buildInfoSize = 32;
|
|
159417
|
+
while (true) {
|
|
159418
|
+
const i = data.toString("binary").indexOf(buildInfoMagic);
|
|
159419
|
+
if (i < 0 || data.length - i < buildInfoSize) {
|
|
159420
|
+
throw Error("not a Go executable");
|
|
159421
|
+
}
|
|
159422
|
+
if (i % buildInfoAlign === 0 && data.length - i >= buildInfoSize) {
|
|
159423
|
+
data = data.subarray(i);
|
|
159424
|
+
break;
|
|
159425
|
+
}
|
|
159426
|
+
data = data.subarray((i + buildInfoAlign - 1) & ~buildInfoAlign);
|
|
159427
|
+
}
|
|
159428
|
+
// Decode the blob.
|
|
159429
|
+
// The first 14 bytes are buildInfoMagic.
|
|
159430
|
+
// The next two bytes indicate pointer size in bytes (4 or 8) and endianness
|
|
159431
|
+
// (0 for little, 1 for big).
|
|
159432
|
+
// Two virtual addresses to Go strings follow that: runtime.buildVersion,
|
|
159433
|
+
// and runtime.modinfo.
|
|
159434
|
+
// On 32-bit platforms, the last 8 bytes are unused.
|
|
159435
|
+
// If the endianness has the 2 bit set, then the pointers are zero
|
|
159436
|
+
// and the 32-byte header is followed by varint-prefixed string data
|
|
159437
|
+
// for the two string values we care about.
|
|
159438
|
+
const ptrSize = data[14];
|
|
159439
|
+
if ((data[15] & 2) !== 0) {
|
|
159440
|
+
data = data.subarray(32);
|
|
159441
|
+
[, data] = decodeString(data);
|
|
159442
|
+
const [mod] = decodeString(data);
|
|
159443
|
+
return mod;
|
|
159444
|
+
}
|
|
159445
|
+
else {
|
|
159446
|
+
const bigEndian = data[15] !== 0;
|
|
159447
|
+
let readPtr;
|
|
159448
|
+
if (ptrSize === 4) {
|
|
159449
|
+
if (bigEndian) {
|
|
159450
|
+
readPtr = (buffer) => buffer.readUInt32BE(0);
|
|
159451
|
+
}
|
|
159452
|
+
else {
|
|
159453
|
+
readPtr = (buffer) => buffer.readUInt32LE(0);
|
|
159454
|
+
}
|
|
159455
|
+
}
|
|
159456
|
+
else {
|
|
159457
|
+
if (bigEndian) {
|
|
159458
|
+
readPtr = (buffer) => Number(buffer.readBigUInt64BE());
|
|
159459
|
+
}
|
|
159460
|
+
else {
|
|
159461
|
+
readPtr = (buffer) => Number(buffer.readBigUInt64LE());
|
|
159462
|
+
}
|
|
159463
|
+
}
|
|
159464
|
+
// The build info blob left by the linker is identified by
|
|
159465
|
+
// a 16-byte header, consisting of buildInfoMagic (14 bytes),
|
|
159466
|
+
// the binary's pointer size (1 byte),
|
|
159467
|
+
// and whether the binary is big endian (1 byte).
|
|
159468
|
+
// Now we attempt to read info after metadata.
|
|
159469
|
+
// From 16th byte to 16th + ptrSize there is a header that points
|
|
159470
|
+
// to go version
|
|
159471
|
+
const version = readString(binary, ptrSize, readPtr, readPtr(data.slice(16, 16 + ptrSize)));
|
|
159472
|
+
if (version === "") {
|
|
159473
|
+
throw Error("no version found in go binary");
|
|
159474
|
+
}
|
|
159475
|
+
// Go version header was right after metadata.
|
|
159476
|
+
// Modules header right after go version
|
|
159477
|
+
// Read next `ptrSize` bytes, this point to the
|
|
159478
|
+
// place where modules info is stored
|
|
159479
|
+
const mod = readString(binary, ptrSize, readPtr, readPtr(data.slice(16 + ptrSize, 16 + 2 * ptrSize)));
|
|
159480
|
+
// This verifies that what we got are actually go modules
|
|
159481
|
+
// First 16 bytes are unicodes as last 16
|
|
159482
|
+
// Mirrors go version source code
|
|
159483
|
+
if (mod.length >= 33 && mod[mod.length - 17] === "\n") {
|
|
159484
|
+
return mod.slice(16, mod.length - 16);
|
|
159485
|
+
}
|
|
159486
|
+
else {
|
|
159487
|
+
throw Error("binary is not built with go module support");
|
|
159488
|
+
}
|
|
159489
|
+
}
|
|
159490
|
+
}
|
|
159491
|
+
exports.readRawBuildInfo = readRawBuildInfo;
|
|
159492
|
+
function decodeString(data) {
|
|
159493
|
+
const num = varint.decode(data);
|
|
159494
|
+
const size = varint.decode.bytes;
|
|
159495
|
+
if (size <= 0 || num >= data.length - size) {
|
|
159496
|
+
return ["", Buffer.from([])];
|
|
159497
|
+
}
|
|
159498
|
+
const res = data.subarray(size, num + size);
|
|
159499
|
+
const rest = data.subarray(num + size);
|
|
159500
|
+
return [res.toString("binary"), rest];
|
|
159501
|
+
}
|
|
159502
|
+
// Source
|
|
159503
|
+
// https://github.com/golang/go/blob/46f99ce7ea97d11b0a1a079da8dda0f51df2a2d2/src/cmd/go/internal/version/exe.go#L105
|
|
159504
|
+
/**
|
|
159505
|
+
* Find start of section that contains module version data
|
|
159506
|
+
* @param binary
|
|
159507
|
+
*/
|
|
159508
|
+
function dataStart(binary) {
|
|
159509
|
+
for (const section of binary.body.sections) {
|
|
159510
|
+
if (section.name === ".go.buildinfo") {
|
|
159511
|
+
return section.addr;
|
|
159512
|
+
}
|
|
159513
|
+
}
|
|
159514
|
+
for (const program of binary.body.programs) {
|
|
159515
|
+
if (program.type === "load" && program.flags.w === true) {
|
|
159516
|
+
return program.vaddr;
|
|
159517
|
+
}
|
|
159518
|
+
}
|
|
159519
|
+
return 0;
|
|
159520
|
+
}
|
|
159521
|
+
// Source
|
|
159522
|
+
// https://github.com/golang/go/blob/46f99ce7ea97d11b0a1a079da8dda0f51df2a2d2/src/cmd/go/internal/version/exe.go#L87
|
|
159523
|
+
/**
|
|
159524
|
+
* Read at most `size` of bytes from `program` that contains byte at `addr`
|
|
159525
|
+
* @param programs
|
|
159526
|
+
* @param addr
|
|
159527
|
+
* @param size
|
|
159528
|
+
*/
|
|
159529
|
+
function readData(programs, addr, size) {
|
|
159530
|
+
for (const program of programs) {
|
|
159531
|
+
const vaddr = program.vaddr;
|
|
159532
|
+
const filesz = program.filesz;
|
|
159533
|
+
if (vaddr <= addr && addr <= vaddr + filesz - 1) {
|
|
159534
|
+
let n = vaddr + filesz - addr;
|
|
159535
|
+
if (n > size) {
|
|
159536
|
+
n = size;
|
|
159537
|
+
}
|
|
159538
|
+
const from = addr - vaddr; // offset from the beginning of the program
|
|
159539
|
+
return program.data.slice(from, from + n);
|
|
159540
|
+
}
|
|
159541
|
+
}
|
|
159542
|
+
return undefined;
|
|
159543
|
+
}
|
|
159544
|
+
// Source
|
|
159545
|
+
// https://github.com/golang/go/blob/46f99ce7ea97d11b0a1a079da8dda0f51df2a2d2/src/cmd/go/internal/version/version.go#L189
|
|
159546
|
+
/**
|
|
159547
|
+
* Function returns the string at address addr in the executable x
|
|
159548
|
+
* @param binaryFile
|
|
159549
|
+
* @param ptrSize
|
|
159550
|
+
* @param readPtr
|
|
159551
|
+
* @param addr
|
|
159552
|
+
*/
|
|
159553
|
+
function readString(binaryFile, ptrSize, readPtr, addr) {
|
|
159554
|
+
const hdr = readData(binaryFile.body.programs, addr, 2 * ptrSize);
|
|
159555
|
+
if (!hdr || hdr.length < 2 * ptrSize) {
|
|
159556
|
+
return "";
|
|
159557
|
+
}
|
|
159558
|
+
const dataAddr = readPtr(hdr);
|
|
159559
|
+
const dataLen = readPtr(hdr.slice(ptrSize));
|
|
159560
|
+
const data = readData(binaryFile.body.programs, dataAddr, dataLen);
|
|
159561
|
+
if (!data || data.length < dataLen) {
|
|
159562
|
+
return "";
|
|
159563
|
+
}
|
|
159564
|
+
return data.toString("binary");
|
|
159565
|
+
}
|
|
159566
|
+
//# sourceMappingURL=go-binary.js.map
|
|
159567
|
+
|
|
159568
|
+
/***/ }),
|
|
159569
|
+
|
|
159570
|
+
/***/ 79160:
|
|
159571
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
159572
|
+
|
|
159573
|
+
"use strict";
|
|
159574
|
+
|
|
159575
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159576
|
+
exports.GoModule = void 0;
|
|
159577
|
+
class GoModule {
|
|
159578
|
+
constructor(name, version) {
|
|
159579
|
+
this.packages = [];
|
|
159580
|
+
this.name = name;
|
|
159581
|
+
this.version = version;
|
|
159582
|
+
}
|
|
159583
|
+
// fullName returns the module's name and version, separated with an `@`. This
|
|
159584
|
+
// reflects how Go stores them on disk (except for vendored paths).
|
|
159585
|
+
fullName() {
|
|
159586
|
+
return this.name + "@" + this.version;
|
|
159587
|
+
}
|
|
159588
|
+
snykNormalisedVersion() {
|
|
159589
|
+
// Versions in Go have leading 'v'
|
|
159590
|
+
let version = this.version.substring(1);
|
|
159591
|
+
// In versions with hash, we only care about hash
|
|
159592
|
+
// v0.0.0-20200905004654-be1d3432aa8f => #be1d3432aa8f
|
|
159593
|
+
version = version.includes("-")
|
|
159594
|
+
? `#${version.substring(version.lastIndexOf("-") + 1)}`
|
|
159595
|
+
: version;
|
|
159596
|
+
return version;
|
|
159597
|
+
}
|
|
159598
|
+
}
|
|
159599
|
+
exports.GoModule = GoModule;
|
|
159600
|
+
//# sourceMappingURL=go-module.js.map
|
|
159601
|
+
|
|
159602
|
+
/***/ }),
|
|
159603
|
+
|
|
159240
159604
|
/***/ 5998:
|
|
159241
159605
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
159242
159606
|
|
|
159243
159607
|
"use strict";
|
|
159244
159608
|
|
|
159245
159609
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159246
|
-
exports.
|
|
159610
|
+
exports.goModulesToScannedProjects = exports.getGoModulesContentAction = exports.DEP_GRAPH_TYPE = void 0;
|
|
159247
159611
|
const elf = __webpack_require__(18);
|
|
159248
159612
|
const event_loop_spinner_1 = __webpack_require__(77158);
|
|
159249
159613
|
const path = __webpack_require__(85622);
|
|
159250
|
-
const
|
|
159251
|
-
const pclntab_1 = __webpack_require__(77162);
|
|
159614
|
+
const go_binary_1 = __webpack_require__(6803);
|
|
159252
159615
|
const ignoredPaths = [
|
|
159253
159616
|
path.normalize("/boot"),
|
|
159254
159617
|
path.normalize("/dev"),
|
|
@@ -159295,21 +159658,17 @@ async function findGoBinaries(stream, streamSize) {
|
|
|
159295
159658
|
const goBuildInfo = binaryFile.body.sections.find((section) => section.name === ".go.buildinfo");
|
|
159296
159659
|
// Could be found in file headers
|
|
159297
159660
|
const goBuildId = binaryFile.body.sections.find((section) => section.name === ".note.go.buildid");
|
|
159298
|
-
const interp = binaryFile.body.sections.find((section) => section.name === ".interp");
|
|
159299
159661
|
if (!goBuildInfo && !goBuildId) {
|
|
159300
159662
|
return resolve(undefined);
|
|
159301
159663
|
}
|
|
159302
|
-
else if (interp) {
|
|
159303
|
-
// Compiled using cgo
|
|
159304
|
-
// we wouldn't be able to extract modules
|
|
159305
|
-
// TODO: cgo-compiled binaries are not supported in this iteration
|
|
159306
|
-
return resolve(undefined);
|
|
159307
|
-
}
|
|
159308
159664
|
else if (goBuildInfo) {
|
|
159309
159665
|
const info = goBuildInfo.data
|
|
159310
159666
|
.slice(0, buildInfoMagic.length)
|
|
159311
159667
|
.toString(encoding);
|
|
159312
159668
|
if (info === buildInfoMagic) {
|
|
159669
|
+
// to make sure we got a Go binary with module support, we try
|
|
159670
|
+
// reading it. Will throw an error if not.
|
|
159671
|
+
(0, go_binary_1.readRawBuildInfo)(binaryFile);
|
|
159313
159672
|
return resolve(binaryFile);
|
|
159314
159673
|
}
|
|
159315
159674
|
return resolve(undefined);
|
|
@@ -159325,6 +159684,9 @@ async function findGoBinaries(stream, streamSize) {
|
|
|
159325
159684
|
// Usually the buildID is simply actionID/contentID, but with exceptions.
|
|
159326
159685
|
// https://github.com/golang/go/blob/master/src/cmd/go/internal/work/buildid.go#L23
|
|
159327
159686
|
if (go === buildIdMagic && buildIdParts.length >= 2) {
|
|
159687
|
+
// to make sure we got a Go binary with module support, we try
|
|
159688
|
+
// reading it. Will throw an error if not.
|
|
159689
|
+
(0, go_binary_1.readRawBuildInfo)(binaryFile);
|
|
159328
159690
|
return resolve(binaryFile);
|
|
159329
159691
|
}
|
|
159330
159692
|
return resolve(undefined);
|
|
@@ -159363,7 +159725,7 @@ async function goModulesToScannedProjects(filePathToContent) {
|
|
|
159363
159725
|
if (event_loop_spinner_1.eventLoopSpinner.isStarving()) {
|
|
159364
159726
|
await event_loop_spinner_1.eventLoopSpinner.spin();
|
|
159365
159727
|
}
|
|
159366
|
-
const depGraph = await
|
|
159728
|
+
const depGraph = await new go_binary_1.GoBinary(goBinary).depGraph();
|
|
159367
159729
|
if (!depGraph) {
|
|
159368
159730
|
continue;
|
|
159369
159731
|
}
|
|
@@ -159382,95 +159744,10 @@ async function goModulesToScannedProjects(filePathToContent) {
|
|
|
159382
159744
|
return scanResults;
|
|
159383
159745
|
}
|
|
159384
159746
|
exports.goModulesToScannedProjects = goModulesToScannedProjects;
|
|
159385
|
-
/**
|
|
159386
|
-
* Reads the given PCLN ELF section from a Go binary and returns
|
|
159387
|
-
* a list of files that have been used to compile that binary.
|
|
159388
|
-
* @param pcln: a buffer containing the ".gopclntab" ELF section
|
|
159389
|
-
*/
|
|
159390
|
-
function readFilesFromPCLNTable(pcln) {
|
|
159391
|
-
return new pclntab_1.LineTable(pcln).go12MapFiles();
|
|
159392
|
-
}
|
|
159393
|
-
exports.readFilesFromPCLNTable = readFilesFromPCLNTable;
|
|
159394
159747
|
//# sourceMappingURL=index.js.map
|
|
159395
159748
|
|
|
159396
159749
|
/***/ }),
|
|
159397
159750
|
|
|
159398
|
-
/***/ 31705:
|
|
159399
|
-
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
159400
|
-
|
|
159401
|
-
"use strict";
|
|
159402
|
-
|
|
159403
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159404
|
-
exports.parseGoBinary = void 0;
|
|
159405
|
-
const depGraph = __webpack_require__(26326);
|
|
159406
|
-
const event_loop_spinner_1 = __webpack_require__(77158);
|
|
159407
|
-
const _1 = __webpack_require__(5998);
|
|
159408
|
-
const str_tab_parser_1 = __webpack_require__(74144);
|
|
159409
|
-
const version_parser_1 = __webpack_require__(12790);
|
|
159410
|
-
/**
|
|
159411
|
-
* Parse `.strtab` to get Go packages
|
|
159412
|
-
* Parse `.go.buildinfo` to get addresses
|
|
159413
|
-
* to go modules and their versions
|
|
159414
|
-
* @param goBinary
|
|
159415
|
-
*/
|
|
159416
|
-
async function parseGoBinary(goBinary) {
|
|
159417
|
-
// Non-stripped binaries contain data on ".strtab" section
|
|
159418
|
-
const strTab = goBinary.body.sections.find((section) => section.name === ".strtab");
|
|
159419
|
-
// TODO: stripped binaries are not supported in this iteration
|
|
159420
|
-
if (!strTab) {
|
|
159421
|
-
return undefined;
|
|
159422
|
-
}
|
|
159423
|
-
const { name, modules } = (0, version_parser_1.extractModulesFromBinary)(goBinary);
|
|
159424
|
-
const packages = (0, str_tab_parser_1.parserStrTab)(strTab.data);
|
|
159425
|
-
// If there is no packages or modules, return empty result
|
|
159426
|
-
if (Object.keys(modules).length === 0 || packages.length === 0) {
|
|
159427
|
-
return undefined;
|
|
159428
|
-
}
|
|
159429
|
-
const packageVersionTable = matchModuleToPackage(modules, packages);
|
|
159430
|
-
return await createDepGraph(name, packageVersionTable);
|
|
159431
|
-
}
|
|
159432
|
-
exports.parseGoBinary = parseGoBinary;
|
|
159433
|
-
/**
|
|
159434
|
-
* Package name consist of module name and path to package.
|
|
159435
|
-
* This function matches package to modules and their versions
|
|
159436
|
-
* @param moduleVersionTable
|
|
159437
|
-
* @param packages
|
|
159438
|
-
*/
|
|
159439
|
-
function matchModuleToPackage(moduleVersionTable, packages) {
|
|
159440
|
-
const resultTable = {};
|
|
159441
|
-
for (const pack of packages) {
|
|
159442
|
-
let moduleVersion = moduleVersionTable[pack];
|
|
159443
|
-
if (!moduleVersion) {
|
|
159444
|
-
const [packageModule] = Object.keys(moduleVersionTable)
|
|
159445
|
-
// Find all modules that this package can be from
|
|
159446
|
-
.filter((moduleName) => pack.startsWith(moduleName))
|
|
159447
|
-
// The longest string will be the closest match
|
|
159448
|
-
.sort((a, b) => b.length - a.length);
|
|
159449
|
-
if (!packageModule || !moduleVersionTable[packageModule]) {
|
|
159450
|
-
continue;
|
|
159451
|
-
}
|
|
159452
|
-
moduleVersion = moduleVersionTable[packageModule];
|
|
159453
|
-
}
|
|
159454
|
-
resultTable[pack] = moduleVersion;
|
|
159455
|
-
}
|
|
159456
|
-
return resultTable;
|
|
159457
|
-
}
|
|
159458
|
-
async function createDepGraph(name, packageVersionTable) {
|
|
159459
|
-
const goModulesDepGraph = new depGraph.DepGraphBuilder({ name: _1.DEP_GRAPH_TYPE }, { name });
|
|
159460
|
-
for (const [name, version] of Object.entries(packageVersionTable)) {
|
|
159461
|
-
if (event_loop_spinner_1.eventLoopSpinner.isStarving()) {
|
|
159462
|
-
await event_loop_spinner_1.eventLoopSpinner.spin();
|
|
159463
|
-
}
|
|
159464
|
-
const nodeId = `${name}@${version}`;
|
|
159465
|
-
goModulesDepGraph.addPkgNode({ name, version }, nodeId);
|
|
159466
|
-
goModulesDepGraph.connectDep(goModulesDepGraph.rootNodeId, nodeId);
|
|
159467
|
-
}
|
|
159468
|
-
return goModulesDepGraph.build();
|
|
159469
|
-
}
|
|
159470
|
-
//# sourceMappingURL=parser.js.map
|
|
159471
|
-
|
|
159472
|
-
/***/ }),
|
|
159473
|
-
|
|
159474
159751
|
/***/ 77162:
|
|
159475
159752
|
/***/ ((__unused_webpack_module, exports) => {
|
|
159476
159753
|
|
|
@@ -159660,262 +159937,6 @@ const littleEndian = {
|
|
|
159660
159937
|
|
|
159661
159938
|
/***/ }),
|
|
159662
159939
|
|
|
159663
|
-
/***/ 74144:
|
|
159664
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
159665
|
-
|
|
159666
|
-
"use strict";
|
|
159667
|
-
|
|
159668
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159669
|
-
exports.parserStrTab = void 0;
|
|
159670
|
-
/**
|
|
159671
|
-
* Because 3rd party imports in Go look like URLs (github.com/bla/bla)
|
|
159672
|
-
* we try to match lines that have URL-like type of string and ends with `..inittask` string
|
|
159673
|
-
* `.inittask` is internal Go mechanism to initialize modules
|
|
159674
|
-
*/
|
|
159675
|
-
const INIT_TASK_LINE_REGEXP = /^\w+\.\w+\/.+\.\.inittask$/;
|
|
159676
|
-
/**
|
|
159677
|
-
* Get all lines in `.strtab` that ends with `..inittask`
|
|
159678
|
-
* `..inittask` is internal go function to init the package
|
|
159679
|
-
* Also lines need to be decoded, cos it might contain HTML encoded symbols
|
|
159680
|
-
* @param strTabSectionBuffer
|
|
159681
|
-
*/
|
|
159682
|
-
function parserStrTab(strTabSectionBuffer) {
|
|
159683
|
-
return (strTabSectionBuffer
|
|
159684
|
-
.toString()
|
|
159685
|
-
// Lines in a strTab are terminated by \u0000 (NULL) symbol
|
|
159686
|
-
.split("\0")
|
|
159687
|
-
// Get only lines that look like go packages
|
|
159688
|
-
.filter((line) => line.match(INIT_TASK_LINE_REGEXP))
|
|
159689
|
-
// Remove trailing `..inittask` from go package
|
|
159690
|
-
.map((line) => decodeURIComponent(line.replace("..inittask", ""))));
|
|
159691
|
-
}
|
|
159692
|
-
exports.parserStrTab = parserStrTab;
|
|
159693
|
-
//# sourceMappingURL=str-tab-parser.js.map
|
|
159694
|
-
|
|
159695
|
-
/***/ }),
|
|
159696
|
-
|
|
159697
|
-
/***/ 12790:
|
|
159698
|
-
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
159699
|
-
|
|
159700
|
-
"use strict";
|
|
159701
|
-
|
|
159702
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159703
|
-
exports.extractModulesFromBinary = void 0;
|
|
159704
|
-
const varint = __webpack_require__(94676);
|
|
159705
|
-
/**
|
|
159706
|
-
* Create same output as `go version -m binary-file` does
|
|
159707
|
-
* @param binary
|
|
159708
|
-
*/
|
|
159709
|
-
function extractModulesFromBinary(binary) {
|
|
159710
|
-
const { version: goVersion, mod } = findVers(binary);
|
|
159711
|
-
const { name, modules } = prepareGoDependencies(mod);
|
|
159712
|
-
return { goVersion, name, modules };
|
|
159713
|
-
}
|
|
159714
|
-
exports.extractModulesFromBinary = extractModulesFromBinary;
|
|
159715
|
-
/**
|
|
159716
|
-
* Normalize versions to align with `snyk-go-parser`
|
|
159717
|
-
* @param mod
|
|
159718
|
-
*/
|
|
159719
|
-
function prepareGoDependencies(mod) {
|
|
159720
|
-
if (!mod) {
|
|
159721
|
-
return { name: "", modules: {} };
|
|
159722
|
-
}
|
|
159723
|
-
const [, mainModuleLine, ...versionsLines] = mod.split("\n");
|
|
159724
|
-
const [, name] = mainModuleLine.split("\t");
|
|
159725
|
-
const modules = {};
|
|
159726
|
-
versionsLines.forEach((versionLine) => {
|
|
159727
|
-
if (!versionLine) {
|
|
159728
|
-
return;
|
|
159729
|
-
}
|
|
159730
|
-
const [, name, ver] = versionLine.split("\t");
|
|
159731
|
-
if (!name || !ver) {
|
|
159732
|
-
return;
|
|
159733
|
-
}
|
|
159734
|
-
// Versions in Go have leading 'v'
|
|
159735
|
-
let version = ver.substring(1);
|
|
159736
|
-
// In versions with hash, we only care about hash
|
|
159737
|
-
// v0.0.0-20200905004654-be1d3432aa8f => #be1d3432aa8f
|
|
159738
|
-
version = version.includes("-")
|
|
159739
|
-
? `#${version.substring(version.lastIndexOf("-") + 1)}`
|
|
159740
|
-
: version;
|
|
159741
|
-
modules[name] = version;
|
|
159742
|
-
});
|
|
159743
|
-
return { name, modules };
|
|
159744
|
-
}
|
|
159745
|
-
// Source
|
|
159746
|
-
// https://github.com/golang/go/blob/master/src/debug/buildinfo/buildinfo.go#L142
|
|
159747
|
-
/**
|
|
159748
|
-
* Function finds and returns the Go version and
|
|
159749
|
-
* module version information in the executable binary
|
|
159750
|
-
* @param binary
|
|
159751
|
-
*/
|
|
159752
|
-
function findVers(binary) {
|
|
159753
|
-
const buildInfoMagic = "\xff Go buildinf:";
|
|
159754
|
-
const result = {
|
|
159755
|
-
version: "",
|
|
159756
|
-
mod: "",
|
|
159757
|
-
};
|
|
159758
|
-
// Read the first 64kB of dataAddr to find the build info blob.
|
|
159759
|
-
// On some platforms, the blob will be in its own section, and DataStart
|
|
159760
|
-
// returns the address of that section. On others, it's somewhere in the
|
|
159761
|
-
// data segment; the linker puts it near the beginning.
|
|
159762
|
-
const dataAddr = dataStart(binary);
|
|
159763
|
-
let data = readData(binary.body.programs, dataAddr, 64 * 1024) || Buffer.from([]);
|
|
159764
|
-
const buildInfoAlign = 16;
|
|
159765
|
-
const buildInfoSize = 32;
|
|
159766
|
-
while (true) {
|
|
159767
|
-
const i = data.toString("binary").indexOf(buildInfoMagic);
|
|
159768
|
-
if (i < 0 || data.length - i < buildInfoSize) {
|
|
159769
|
-
return result;
|
|
159770
|
-
}
|
|
159771
|
-
if (i % buildInfoAlign === 0 && data.length - i >= buildInfoSize) {
|
|
159772
|
-
data = data.subarray(i);
|
|
159773
|
-
break;
|
|
159774
|
-
}
|
|
159775
|
-
data = data.subarray((i + buildInfoAlign - 1) & ~buildInfoAlign);
|
|
159776
|
-
}
|
|
159777
|
-
// Decode the blob.
|
|
159778
|
-
// The first 14 bytes are buildInfoMagic.
|
|
159779
|
-
// The next two bytes indicate pointer size in bytes (4 or 8) and endianness
|
|
159780
|
-
// (0 for little, 1 for big).
|
|
159781
|
-
// Two virtual addresses to Go strings follow that: runtime.buildVersion,
|
|
159782
|
-
// and runtime.modinfo.
|
|
159783
|
-
// On 32-bit platforms, the last 8 bytes are unused.
|
|
159784
|
-
// If the endianness has the 2 bit set, then the pointers are zero
|
|
159785
|
-
// and the 32-byte header is followed by varint-prefixed string data
|
|
159786
|
-
// for the two string values we care about.
|
|
159787
|
-
const ptrSize = data[14];
|
|
159788
|
-
if ((data[15] & 2) !== 0) {
|
|
159789
|
-
data = data.subarray(32);
|
|
159790
|
-
[result.version, data] = decodeString(data);
|
|
159791
|
-
[result.mod, data] = decodeString(data);
|
|
159792
|
-
}
|
|
159793
|
-
else {
|
|
159794
|
-
const bigEndian = data[15] !== 0;
|
|
159795
|
-
let readPtr;
|
|
159796
|
-
if (ptrSize === 4) {
|
|
159797
|
-
if (bigEndian) {
|
|
159798
|
-
readPtr = (buffer) => buffer.readUInt32BE(0);
|
|
159799
|
-
}
|
|
159800
|
-
else {
|
|
159801
|
-
readPtr = (buffer) => buffer.readUInt32LE(0);
|
|
159802
|
-
}
|
|
159803
|
-
}
|
|
159804
|
-
else {
|
|
159805
|
-
if (bigEndian) {
|
|
159806
|
-
readPtr = (buffer) => Number(buffer.readBigUInt64BE());
|
|
159807
|
-
}
|
|
159808
|
-
else {
|
|
159809
|
-
readPtr = (buffer) => Number(buffer.readBigUInt64LE());
|
|
159810
|
-
}
|
|
159811
|
-
}
|
|
159812
|
-
// The build info blob left by the linker is identified by
|
|
159813
|
-
// a 16-byte header, consisting of buildInfoMagic (14 bytes),
|
|
159814
|
-
// the binary's pointer size (1 byte),
|
|
159815
|
-
// and whether the binary is big endian (1 byte).
|
|
159816
|
-
// Now we attempt to read info after metadata.
|
|
159817
|
-
// From 16th byte to 16th + ptrSize there is a header that points
|
|
159818
|
-
// to go version
|
|
159819
|
-
const version = readString(binary, ptrSize, readPtr, readPtr(data.slice(16, 16 + ptrSize)));
|
|
159820
|
-
if (version === "") {
|
|
159821
|
-
return result;
|
|
159822
|
-
}
|
|
159823
|
-
result.version = version;
|
|
159824
|
-
// Go version header was right after metadata.
|
|
159825
|
-
// Modules header right after go version
|
|
159826
|
-
// Read next `ptrSize` bytes, this point to the
|
|
159827
|
-
// place where modules info is stored
|
|
159828
|
-
const mod = readString(binary, ptrSize, readPtr, readPtr(data.slice(16 + ptrSize, 16 + 2 * ptrSize)));
|
|
159829
|
-
// This verifies that what we got are actually go modules
|
|
159830
|
-
// First 16 bytes are unicodes as last 16
|
|
159831
|
-
// Mirrors go version source code
|
|
159832
|
-
if (mod.length >= 33 && mod[mod.length - 17] === "\n") {
|
|
159833
|
-
result.mod = mod.slice(16, mod.length - 16);
|
|
159834
|
-
}
|
|
159835
|
-
else {
|
|
159836
|
-
result.mod = "";
|
|
159837
|
-
}
|
|
159838
|
-
}
|
|
159839
|
-
return result;
|
|
159840
|
-
}
|
|
159841
|
-
function decodeString(data) {
|
|
159842
|
-
const num = varint.decode(data);
|
|
159843
|
-
const size = varint.decode.bytes;
|
|
159844
|
-
if (size <= 0 || num >= data.length - size) {
|
|
159845
|
-
return ["", Buffer.from([])];
|
|
159846
|
-
}
|
|
159847
|
-
const res = data.subarray(size, num + size);
|
|
159848
|
-
const rest = data.subarray(num + size);
|
|
159849
|
-
return [res.toString("binary"), rest];
|
|
159850
|
-
}
|
|
159851
|
-
// Source
|
|
159852
|
-
// https://github.com/golang/go/blob/46f99ce7ea97d11b0a1a079da8dda0f51df2a2d2/src/cmd/go/internal/version/exe.go#L105
|
|
159853
|
-
/**
|
|
159854
|
-
* Find start of section that contains module version data
|
|
159855
|
-
* @param binary
|
|
159856
|
-
*/
|
|
159857
|
-
function dataStart(binary) {
|
|
159858
|
-
for (const section of binary.body.sections) {
|
|
159859
|
-
if (section.name === ".go.buildinfo") {
|
|
159860
|
-
return section.addr;
|
|
159861
|
-
}
|
|
159862
|
-
}
|
|
159863
|
-
for (const program of binary.body.programs) {
|
|
159864
|
-
if (program.type === "load" && program.flags.w === true) {
|
|
159865
|
-
return program.vaddr;
|
|
159866
|
-
}
|
|
159867
|
-
}
|
|
159868
|
-
return 0;
|
|
159869
|
-
}
|
|
159870
|
-
// Source
|
|
159871
|
-
// https://github.com/golang/go/blob/46f99ce7ea97d11b0a1a079da8dda0f51df2a2d2/src/cmd/go/internal/version/exe.go#L87
|
|
159872
|
-
/**
|
|
159873
|
-
* Read at most `size` of bytes from `program` that contains byte at `addr`
|
|
159874
|
-
* @param programs
|
|
159875
|
-
* @param addr
|
|
159876
|
-
* @param size
|
|
159877
|
-
*/
|
|
159878
|
-
function readData(programs, addr, size) {
|
|
159879
|
-
for (const program of programs) {
|
|
159880
|
-
const vaddr = program.vaddr;
|
|
159881
|
-
const filesz = program.filesz;
|
|
159882
|
-
if (vaddr <= addr && addr <= vaddr + filesz - 1) {
|
|
159883
|
-
let n = vaddr + filesz - addr;
|
|
159884
|
-
if (n > size) {
|
|
159885
|
-
n = size;
|
|
159886
|
-
}
|
|
159887
|
-
const from = addr - vaddr; // offset from the beginning of the program
|
|
159888
|
-
return program.data.slice(from, from + n);
|
|
159889
|
-
}
|
|
159890
|
-
}
|
|
159891
|
-
return undefined;
|
|
159892
|
-
}
|
|
159893
|
-
// Source
|
|
159894
|
-
// https://github.com/golang/go/blob/46f99ce7ea97d11b0a1a079da8dda0f51df2a2d2/src/cmd/go/internal/version/version.go#L189
|
|
159895
|
-
/**
|
|
159896
|
-
* Function returns the string at address addr in the executable x
|
|
159897
|
-
* @param binaryFile
|
|
159898
|
-
* @param ptrSize
|
|
159899
|
-
* @param readPtr
|
|
159900
|
-
* @param addr
|
|
159901
|
-
*/
|
|
159902
|
-
function readString(binaryFile, ptrSize, readPtr, addr) {
|
|
159903
|
-
const hdr = readData(binaryFile.body.programs, addr, 2 * ptrSize);
|
|
159904
|
-
if (!hdr || hdr.length < 2 * ptrSize) {
|
|
159905
|
-
return "";
|
|
159906
|
-
}
|
|
159907
|
-
const dataAddr = readPtr(hdr);
|
|
159908
|
-
const dataLen = readPtr(hdr.slice(ptrSize));
|
|
159909
|
-
const data = readData(binaryFile.body.programs, dataAddr, dataLen);
|
|
159910
|
-
if (!data || data.length < dataLen) {
|
|
159911
|
-
return "";
|
|
159912
|
-
}
|
|
159913
|
-
return data.toString("binary");
|
|
159914
|
-
}
|
|
159915
|
-
//# sourceMappingURL=version-parser.js.map
|
|
159916
|
-
|
|
159917
|
-
/***/ }),
|
|
159918
|
-
|
|
159919
159940
|
/***/ 89313:
|
|
159920
159941
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
159921
159942
|
|