snyk-docker-plugin
Version:
Snyk CLI docker plugin
159 lines • 5.14 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.purl = exports.analyzeDistroless = exports.analyze = void 0;
const packageurl_js_1 = require("packageurl-js");
const types_1 = require("../types");
function analyze(targetImage, aptFiles, osRelease) {
const pkgs = parseDpkgFile(aptFiles.dpkgFile, osRelease);
if (aptFiles.extFile) {
setAutoInstalledPackages(aptFiles.extFile, pkgs);
}
return Promise.resolve({
Image: targetImage,
AnalyzeType: types_1.AnalysisType.Apt,
Analysis: pkgs,
});
}
exports.analyze = analyze;
function analyzeDistroless(targetImage, aptFiles, osRelease) {
const analyzedPackages = [];
for (const fileContent of aptFiles) {
const currentPackages = parseDpkgFile(fileContent, osRelease);
analyzedPackages.push(...currentPackages);
}
return Promise.resolve({
Image: targetImage,
AnalyzeType: types_1.AnalysisType.Apt,
Analysis: analyzedPackages,
});
}
exports.analyzeDistroless = analyzeDistroless;
function parseDpkgFile(text, osRelease) {
const pkgs = [];
let curPkg = null;
for (const line of text.split("\n")) {
curPkg = parseDpkgLine(line, curPkg, pkgs);
if (curPkg) {
curPkg.Purl = purl(curPkg, osRelease);
}
}
return pkgs;
}
const debianCodenames = new Map([
["8", "jessie"],
["9", "stretch"],
["10", "buster"],
["11", "bullseye"],
["12", "bookworm"],
["13", "trixie"],
["unstable", "sid"],
]);
function purl(curPkg, osRelease) {
var _a;
let vendor = "";
if (!curPkg.Name || !curPkg.Version) {
return undefined;
}
const qualifiers = {};
if (curPkg.Source && curPkg.SourceVersion) {
qualifiers.upstream = `${curPkg.Source}@${curPkg.SourceVersion}`;
}
else if (curPkg.Source) {
qualifiers.upstream = curPkg.Source;
}
if (osRelease) {
const codenameOrVersion = (_a = debianCodenames.get(osRelease.version)) !== null && _a !== void 0 ? _a : osRelease.version;
qualifiers.distro = `${osRelease.name}-${codenameOrVersion}`;
vendor = osRelease.name;
}
return new packageurl_js_1.PackageURL("deb", vendor, curPkg.Name, curPkg.Version,
// make sure that we pass in undefined if there are no qualifiers, because
// the packageurl-js library doesn't handle that properly...
Object.keys(qualifiers).length !== 0 ? qualifiers : undefined, undefined).toString();
}
exports.purl = purl;
function parseDpkgLine(text, curPkg, pkgs) {
const [key, value] = text.split(": ");
switch (key) {
case "Package":
curPkg = {
Name: value,
Version: "",
Source: undefined,
SourceVersion: undefined,
Provides: [],
Deps: {},
AutoInstalled: undefined,
};
pkgs.push(curPkg);
break;
case "Version":
curPkg.Version = value;
break;
case "Source":
/**
* The value may look something like this:
* libgcc6 (1.3.0-b1)
* <name> (<version>)
*
* For example, Syft matches these values with a regex:
* https://github.com/anchore/syft/blob/1764e1c3f6bd66781f8350d957a1f95e4d9ad3de/syft/pkg/cataloger/deb/parse_dpkg_db.go#L169-L173
*/
const parts = value.split(" ");
curPkg.Source = parts[0];
if (parts.length > 1) {
curPkg.SourceVersion = parts[1]
.trim()
.replace("(", "")
.replace(")", "");
}
break;
case "Provides":
for (let name of value.split(",")) {
name = name.trim().split(" ")[0];
curPkg.Provides.push(name);
}
break;
case "Pre-Depends":
case "Depends":
for (const depElem of value.split(",")) {
for (let name of depElem.split("|")) {
name = name.trim().split(" ")[0];
curPkg.Deps[name] = true;
}
}
break;
}
return curPkg;
}
function setAutoInstalledPackages(text, pkgs) {
const autoPkgs = parseExtFile(text);
for (const pkg of pkgs) {
if (autoPkgs[pkg.Name]) {
pkg.AutoInstalled = true;
}
}
}
function parseExtFile(text) {
const pkgMap = {};
let curPkgName = null;
for (const line of text.split("\n")) {
curPkgName = parseExtLine(line, curPkgName, pkgMap);
}
return pkgMap;
}
function parseExtLine(text, curPkgName, pkgMap) {
const [key, value] = text.split(": ");
switch (key) {
case "Package":
curPkgName = value;
break;
case "Auto-Installed":
if (parseInt(value, 10) === 1) {
pkgMap[curPkgName] = true;
}
break;
}
return curPkgName;
}
//# sourceMappingURL=apt.js.map
;