UNPKG

@nodesecure/vulnera

Version:

NodeSecure vulnerabilities strategies

81 lines 3.49 kB
// Import Internal Dependencies import * as utils from "../utils.js"; import { VULN_MODE } from "../constants.js"; import { formatVulnsPayload } from "../formats/index.js"; import { Sonatype } from "../database/index.js"; // CONSTANTS const kRatelimitChunkSize = 128; export function SonatypeStrategy(options) { const { credential } = options; const sonatype = new Sonatype({ credential }); return { strategy: VULN_MODE.SONATYPE, hydratePayloadDependencies: hydratePayloadDependencies.bind(null, sonatype) }; } /** * If the package name contains a scope, it must be percent encoded to be spec compliant. * Otherwise, the Package URL is simply <package-name>@<package-version>. * See: https://github.com/package-url/purl-spec */ function toPackageURL(fullPackageName, packageVersion) { const isPackageNameScoped = fullPackageName.includes("/"); if (isPackageNameScoped) { const [scope, packageName] = fullPackageName.split("/"); // Each scope segment must be a percent-encoded string const scopeEncoded = encodeURIComponent(scope); return `pkg:npm/${scopeEncoded}/${packageName}@${packageVersion}`; } return `pkg:npm/${fullPackageName}@${packageVersion}`; } /** * Coordinates are Sonatype's component identifiers, we must build them * using package's name and different package's versions */ function createPackageURLCoordinates([dependencyName, dependencyPayload]) { const { versions } = dependencyPayload; return Object.keys(versions).map((version) => toPackageURL(dependencyName, version)); } async function fetchDataForPackageURLs(sonatype, unchunkedCoordinates) { try { const chunkedCoordinates = [ ...utils.chunkArray(unchunkedCoordinates, kRatelimitChunkSize) ]; return sonatype.findMany({ coordinates: chunkedCoordinates }); } catch { return []; } } /** * When targetting npm repositories, the specification is the following: * pkg:npm/<package-name>@<package-version> such as: pkg:npm/foobar@12.3.1 * For further reading see: https://github.com/package-url/purl-spec */ function extractNameFromPackageURL(purl) { const [, packageData] = purl.split("npm/"); const [packageName] = packageData.split("@"); return decodeURIComponent(packageName); } /** * Package's name is not part of the vulnerability description returned back * by Sonatype. Given that the package name is required in the NodeSecure * vulnerability standard format, we must be sure to provide it back after * reaching the API. */ function vulnWithPackageName(packageName) { return function provideNameToVulnPayload(vuln) { return { ...vuln, package: packageName }; }; } async function hydratePayloadDependencies(sonatype, dependencies, options = {}) { const packageURLsData = await fetchDataForPackageURLs(sonatype, Array.from(dependencies).flatMap(createPackageURLCoordinates)); const formatVulnerabilities = formatVulnsPayload(options.useFormat); for (const sonatypeResponse of packageURLsData) { const packageName = extractNameFromPackageURL(sonatypeResponse.coordinates); const formattedVulnerabilities = formatVulnerabilities(VULN_MODE.SONATYPE, sonatypeResponse.vulnerabilities.map(vulnWithPackageName(packageName))); const { vulnerabilities } = dependencies.get(packageName); vulnerabilities.push(...formattedVulnerabilities); } } //# sourceMappingURL=sonatype.js.map