UNPKG

snyk-docker-plugin

Version:
160 lines 6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildTree = void 0; /** @deprecated Should implement a new function to build a dependency graph instead. */ function buildTree(targetImage, depType, depInfosList, targetOS) { // A tag can only occur in the last section of a docker image name, so // check any colon separator after the final '/'. If there are no '/', // which is common when using Docker's official images such as // "debian:stretch", just check for ':' const finalSlash = targetImage.lastIndexOf("/"); const hasVersion = (finalSlash >= 0 && targetImage.slice(finalSlash).includes(":")) || targetImage.includes(":"); // Defaults for simple images from dockerhub, like "node" or "centos" let imageName = targetImage; let imageVersion = "latest"; // If we have a version, split on the last ':' to avoid the optional // port on a hostname (i.e. localhost:5000) if (hasVersion) { const versionSeparator = targetImage.lastIndexOf(":"); imageName = targetImage.slice(0, versionSeparator); imageVersion = targetImage.slice(versionSeparator + 1); } if (imageName.endsWith(".tar")) { imageVersion = ""; } const shaString = "@sha256"; if (imageName.endsWith(shaString)) { imageName = imageName.slice(0, imageName.length - shaString.length); imageVersion = ""; } const root = { // don't use the real image name to avoid scanning it as an issue name: "docker-image|" + imageName, version: imageVersion, targetOS, packageFormatVersion: depType + ":0.0.1", dependencies: {}, }; const depsMap = depInfosList.reduce((acc, depInfo) => { const name = depInfo.Name; acc[name] = depInfo; return acc; }, {}); const virtualDepsMap = depInfosList.reduce((acc, depInfo) => { const providesNames = depInfo.Provides || []; for (const name of providesNames) { acc[name] = depInfo; } return acc; }, {}); const depsCounts = {}; for (const depInfo of depInfosList) { countDepsRecursive(depInfo.Name, new Set(), depsMap, virtualDepsMap, depsCounts); } const DEP_FREQ_THRESHOLD = 100; const tooFrequentDepNames = Object.keys(depsCounts).filter((depName) => { return depsCounts[depName] > DEP_FREQ_THRESHOLD; }); const attachDeps = (depInfos) => { const depNamesToSkip = new Set(tooFrequentDepNames); for (const depInfo of depInfos) { const subtree = buildTreeRecursive(depInfo.Name, new Set(), depsMap, virtualDepsMap, depNamesToSkip); if (subtree) { root.dependencies[subtree.name] = subtree; } } }; // attach (as direct deps) pkgs not marked auto-installed: const manuallyInstalledDeps = depInfosList.filter((depInfo) => { return !depInfo.AutoInstalled; }); attachDeps(manuallyInstalledDeps); // attach (as direct deps) pkgs marked as auto-insatalled, // but not dependant upon: const notVisitedDeps = depInfosList.filter((depInfo) => { const depName = depInfo.Name; return !depsMap[depName]._visited; }); attachDeps(notVisitedDeps); // group all the "too frequest" deps under a meta package: if (tooFrequentDepNames.length > 0) { const tooFrequentDeps = tooFrequentDepNames.map((name) => { return depsMap[name]; }); const metaSubtree = { name: "meta-common-packages", version: "meta", dependencies: {}, }; for (const depInfo of tooFrequentDeps) { const pkg = { name: depFullName(depInfo), version: depInfo.Version, }; metaSubtree.dependencies[pkg.name] = pkg; } root.dependencies[metaSubtree.name] = metaSubtree; } return root; } exports.buildTree = buildTree; function buildTreeRecursive(depName, ancestors, depsMap, virtualDepsMap, depNamesToSkip) { const depInfo = depsMap[depName] || virtualDepsMap[depName]; if (!depInfo) { return null; } // "realName" as the argument depName might be a virtual pkg const realName = depInfo.Name; const fullName = depFullName(depInfo); if (ancestors.has(fullName) || depNamesToSkip.has(realName)) { return null; } const tree = { name: fullName, version: depInfo.Version, }; if (depInfo._visited) { return tree; } depInfo._visited = true; const newAncestors = new Set(ancestors).add(fullName); const deps = depInfo.Deps || {}; for (const name of Object.keys(deps)) { const subTree = buildTreeRecursive(name, newAncestors, depsMap, virtualDepsMap, depNamesToSkip); if (subTree) { if (!tree.dependencies) { tree.dependencies = {}; } if (!tree.dependencies[subTree.name]) { tree.dependencies[subTree.name] = subTree; } } } return tree; } function countDepsRecursive(depName, ancestors, depsMap, virtualDepsMap, depCounts) { const depInfo = depsMap[depName] || virtualDepsMap[depName]; if (!depInfo) { return; } // "realName" as the argument depName might be a virtual pkg const realName = depInfo.Name; if (ancestors.has(realName)) { return; } depCounts[realName] = (depCounts[realName] || 0) + 1; const newAncestors = new Set(ancestors).add(realName); const deps = depInfo.Deps || {}; for (const name of Object.keys(deps)) { countDepsRecursive(name, newAncestors, depsMap, virtualDepsMap, depCounts); } } function depFullName(depInfo) { let fullName = depInfo.Name; if (depInfo.Source) { fullName = depInfo.Source + "/" + fullName; } return fullName; } //# sourceMappingURL=index.js.map