UNPKG

snyk-docker-plugin

Version:
126 lines 6.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.truncateAdditionalFacts = exports.RESPONSE_SIZE_LIMITS = exports.isValidDockerImageReference = void 0; /** * Validates a Docker image reference format using the official Docker reference regex. * @param imageReference The Docker image reference to validate * @returns true if valid, false if invalid */ function isValidDockerImageReference(imageReference) { // Docker image reference validation regex from the official Docker packages: // https://github.com/distribution/reference/blob/ff14fafe2236e51c2894ac07d4bdfc778e96d682/regexp.go#L9 // Original regex: ^((?:(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))*|\[(?:[a-fA-F0-9:]+)\])(?::[0-9]+)?/)?[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*)(?::([\w][\w.-]{0,127}))?(?:@([A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}))?$ // Note: Converted [[:xdigit:]] to [a-fA-F0-9] and escaped the forward slashes for JavaScript compatibility. const dockerImageRegex = /^((?:(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))*|\[(?:[a-fA-F0-9:]+)\])(?::[0-9]+)?\/)?[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*)(?::([\w][\w.-]{0,127}))?(?:@([A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][a-fA-F0-9]{32,}))?$/; return dockerImageRegex.test(imageReference); } exports.isValidDockerImageReference = isValidDockerImageReference; // array[*] indicates to truncate each element to the indicated size exports.RESPONSE_SIZE_LIMITS = { "containerConfig.data.user": { type: "string", limit: 1024 }, "containerConfig.data.exposedPorts": { type: "array", limit: 500 }, "containerConfig.data.exposedPorts[*]": { type: "string", limit: 64 }, "containerConfig.data.env": { type: "array", limit: 500 }, "containerConfig.data.env[*]": { type: "string", limit: 1024 }, "containerConfig.data.entrypoint": { type: "array", limit: 500 }, "containerConfig.data.entrypoint[*]": { type: "string", limit: 1024 }, "containerConfig.data.cmd": { type: "array", limit: 500 }, "containerConfig.data.cmd[*]": { type: "string", limit: 1024 }, "containerConfig.data.volumes": { type: "array", limit: 500 }, "containerConfig.data.volumes[*]": { type: "string", limit: 1024 }, "containerConfig.data.workingDir": { type: "string", limit: 1024 }, "containerConfig.data.stopSignal": { type: "string", limit: 128 }, "history.data": { type: "array", limit: 1000 }, "history.data[*].author": { type: "string", limit: 128 }, "history.data[*].createdBy": { type: "string", limit: 4096 }, "history.data[*].comment": { type: "string", limit: 4096 }, }; function truncateAdditionalFacts(facts) { const truncationTracker = {}; const processedFacts = facts.map((fact) => { if (!fact || !fact.type || !fact.data) { return fact; } if (fact.type === "depGraph") { return fact; } const truncatedData = truncateDataValue(fact.data, fact.type, "data", truncationTracker); return { ...fact, data: truncatedData }; }); if (Object.keys(truncationTracker).length > 0) { const existingWarnings = processedFacts.find((f) => f.type === "pluginWarnings"); if (existingWarnings) { existingWarnings.data.truncatedFacts = truncationTracker; } else { const pluginWarningsFact = { type: "pluginWarnings", data: { truncatedFacts: truncationTracker, }, }; processedFacts.push(pluginWarningsFact); } } return processedFacts; } exports.truncateAdditionalFacts = truncateAdditionalFacts; function hasAnyLimitsForPath(factType, path) { const prefix = `${factType}.${path}`; return Object.keys(exports.RESPONSE_SIZE_LIMITS).some((limitKey) => limitKey.startsWith(prefix)); } function truncateDataValue(value, factType, path, truncationTracker) { const limitKey = `${factType}.${path}`; const limitConfig = exports.RESPONSE_SIZE_LIMITS[limitKey]; // directly truncate if there's a match if (limitConfig) { value = truncateValue(value, limitConfig, limitKey, truncationTracker); } if (!hasAnyLimitsForPath(factType, path)) { return value; } if (Array.isArray(value)) { return value.map((item, index) => { return truncateDataValue(item, factType, `${path}[*]`, truncationTracker); }); } else if (typeof value === "object" && value !== null) { const truncatedObject = {}; for (const [key, subValue] of Object.entries(value)) { truncatedObject[key] = truncateDataValue(subValue, factType, `${path}.${key}`, truncationTracker); } return truncatedObject; } return value; } function truncateValue(value, limitConfig, fieldPath, truncationTracker) { switch (limitConfig.type) { case "array": if (Array.isArray(value) && value.length > limitConfig.limit) { const truncatedCount = value.length - limitConfig.limit; // report how many elements were truncated truncationTracker[fieldPath] = { type: "array", countAboveLimit: truncatedCount, }; return value.slice(0, limitConfig.limit); } break; case "string": if (typeof value === "string" && value.length > limitConfig.limit) { const truncatedCount = value.length - limitConfig.limit; // report the maximum number of characters that were truncated for this field const existing = truncationTracker[fieldPath]; if (!existing || truncatedCount > existing.countAboveLimit) { truncationTracker[fieldPath] = { type: "string", countAboveLimit: truncatedCount, }; } return value.substring(0, limitConfig.limit); } break; } return value; } //# sourceMappingURL=utils.js.map