UNPKG

@cyclonedx/cdxgen

Version:

Creates CycloneDX Software Bill of Materials (SBOM) from source or container image

118 lines (113 loc) 3.71 kB
import { Buffer } from "node:buffer"; import { hasDangerousUnicode } from "../utils.js"; /** * Returns the Dependency-Track BOM API URL as a sanitized URL object. * * @param {string} serverUrl Dependency-Track server URL * @returns {URL | undefined} API URL to submit BOM payload */ export function getDependencyTrackBomApiUrl(serverUrl) { const rawServerUrl = `${serverUrl || ""}`.trim(); if (!rawServerUrl || hasDangerousUnicode(rawServerUrl)) { return undefined; } let parsedUrl; try { parsedUrl = new URL(rawServerUrl); } catch { return undefined; } if (!["http:", "https:"].includes(parsedUrl.protocol)) { return undefined; } if (!parsedUrl.hostname || hasDangerousUnicode(parsedUrl.hostname)) { return undefined; } parsedUrl.username = ""; parsedUrl.password = ""; parsedUrl.search = ""; parsedUrl.hash = ""; parsedUrl.pathname = `${parsedUrl.pathname.replace(/\/+$/, "")}/api/v1/bom`; return parsedUrl; } /** * Returns the Dependency-Track BOM API URL string. * * @param {string} serverUrl Dependency-Track server URL * @returns {string | undefined} API URL to submit BOM payload */ export function getDependencyTrackBomUrl(serverUrl) { return getDependencyTrackBomApiUrl(serverUrl)?.toString(); } /** * Build the payload for Dependency-Track BOM submission. * * @param {Object} args CLI/server arguments * @param {Object} bomContents BOM Json * @returns {Object | undefined} payload object if project coordinates are valid */ export function buildDependencyTrackBomPayload(args, bomContents) { let encodedBomContents = Buffer.from(JSON.stringify(bomContents)).toString( "base64", ); if (encodedBomContents.startsWith("77u/")) { encodedBomContents = encodedBomContents.substring(4); } const autoCreate = typeof args.autoCreate === "boolean" ? args.autoCreate : args.autoCreate !== "false"; const bomPayload = { autoCreate: String(autoCreate), bom: encodedBomContents, }; if ( typeof args.projectId !== "undefined" || typeof args.projectName !== "undefined" ) { if (typeof args.projectId !== "undefined") { bomPayload.project = args.projectId; } if (typeof args.projectName !== "undefined") { bomPayload.projectName = args.projectName; } // Dependency-Track submissions use "main" as fallback when no version is provided. bomPayload.projectVersion = args.projectVersion || "main"; } else { return undefined; } const parentProjectId = args.parentProjectId || args.parentUUID; const hasParentUuidMode = typeof parentProjectId !== "undefined"; const hasParentName = typeof args.parentProjectName !== "undefined"; const hasParentVersion = typeof args.parentProjectVersion !== "undefined"; const hasParentCoordsMode = hasParentName || hasParentVersion; if (hasParentUuidMode && hasParentCoordsMode) { return undefined; } if (!hasParentUuidMode && hasParentName !== hasParentVersion) { return undefined; } if (hasParentUuidMode) { bomPayload.parentUUID = parentProjectId; } if (hasParentName && hasParentVersion) { bomPayload.parentName = args.parentProjectName; bomPayload.parentVersion = args.parentProjectVersion; } if ( typeof args.isLatest === "boolean" || args.isLatest === "true" || args.isLatest === "false" ) { bomPayload.isLatest = typeof args.isLatest === "boolean" ? args.isLatest : args.isLatest === "true"; } if (typeof args.projectTag !== "undefined") { bomPayload.projectTags = ( Array.isArray(args.projectTag) ? args.projectTag : [args.projectTag] ).map((tag) => ({ name: tag })); } return bomPayload; }