UNPKG

@socketsecurity/lib

Version:

Core utilities and infrastructure for Socket.dev security tools

181 lines (180 loc) 6.14 kB
"use strict"; /* Socket Lib - Built with esbuild */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var provenance_exports = {}; __export(provenance_exports, { fetchPackageProvenance: () => fetchPackageProvenance, getProvenanceDetails: () => getProvenanceDetails }); module.exports = __toCommonJS(provenance_exports); var import_agents = require("#constants/agents"); var import_abort = require("../abort"); var import_url = require("../url"); const ArrayIsArray = Array.isArray; const SLSA_PROVENANCE_V0_2 = "https://slsa.dev/provenance/v0.2"; const SLSA_PROVENANCE_V1_0 = "https://slsa.dev/provenance/v1"; let _fetcher; // @__NO_SIDE_EFFECTS__ function getFetcher() { if (_fetcher === void 0) { const makeFetchHappen = require("../external/make-fetch-happen"); const { getPacoteCachePath } = require("../constants/packages"); _fetcher = makeFetchHappen.defaults({ cachePath: getPacoteCachePath(), // Prefer-offline: Staleness checks for cached data will be bypassed, but // missing data will be requested from the server. // https://github.com/npm/make-fetch-happen?tab=readme-ov-file#--optscache cache: "force-cache" }); } return _fetcher; } function getAttestations(attestationData) { const data = attestationData; if (!data.attestations || !ArrayIsArray(data.attestations)) { return []; } return data.attestations.filter((attestation) => { const att = attestation; return att.predicateType === SLSA_PROVENANCE_V0_2 || att.predicateType === SLSA_PROVENANCE_V1_0; }); } function findProvenance(attestations) { for (const attestation of attestations) { const att = attestation; try { let predicate = att.predicate; if (!predicate && att.bundle?.dsseEnvelope?.payload) { try { const decodedPayload = Buffer.from( att.bundle.dsseEnvelope.payload, "base64" ).toString("utf8"); const statement = JSON.parse(decodedPayload); predicate = statement.predicate; } catch { continue; } } const predicateData = predicate; if (predicateData?.buildDefinition?.externalParameters) { return { predicate, externalParameters: predicateData.buildDefinition.externalParameters }; } } catch { } } return void 0; } function isTrustedPublisher(value) { if (typeof value !== "string" || !value) { return false; } let url = (0, import_url.parseUrl)(value); let hostname = url?.hostname; if (!url && value.includes("@")) { const firstPart = value.split("@")[0]; if (firstPart) { url = (0, import_url.parseUrl)(firstPart); } if (url) { hostname = url.hostname; } } if (!url) { const httpsUrl = (0, import_url.parseUrl)(`https://${value}`); if (httpsUrl) { hostname = httpsUrl.hostname; } } if (hostname) { return hostname === "github.com" || hostname.endsWith(".github.com") || hostname === "gitlab.com" || hostname.endsWith(".gitlab.com"); } return value.includes("github") || value.includes("gitlab"); } function getProvenanceDetails(attestationData) { const attestations = getAttestations(attestationData); if (!attestations.length) { return void 0; } const provenance = findProvenance(attestations); if (!provenance) { return { level: "attested" }; } const provenanceData = provenance; const { externalParameters, predicate } = provenanceData; const def = predicate?.buildDefinition; const workflow = externalParameters?.workflow; const workflowRef = workflow?.ref || externalParameters?.workflow_ref; const workflowUrl = externalParameters?.context; const workflowPlatform = def?.buildType; const repository = workflow?.repository || externalParameters?.repository; const gitRef = externalParameters?.ref || workflow?.ref; const commitSha = externalParameters?.sha; const workflowRunId = externalParameters?.run_id; const trusted = isTrustedPublisher(workflowRef) || isTrustedPublisher(workflowUrl) || isTrustedPublisher(workflowPlatform) || isTrustedPublisher(repository); return { commitSha, gitRef, level: trusted ? "trusted" : "attested", repository, workflowRef, workflowUrl, workflowPlatform, workflowRunId }; } // @__NO_SIDE_EFFECTS__ async function fetchPackageProvenance(pkgName, pkgVersion, options) { const { signal, timeout = 1e4 } = { __proto__: null, ...options }; if (signal?.aborted) { return void 0; } const timeoutSignal = (0, import_abort.createTimeoutSignal)(timeout); const compositeSignal = (0, import_abort.createCompositeAbortSignal)(signal, timeoutSignal); const fetcher = /* @__PURE__ */ getFetcher(); try { const response = await fetcher( // The npm registry attestations API endpoint. `${import_agents.NPM_REGISTRY_URL}/-/npm/v1/attestations/${encodeURIComponent(pkgName)}@${encodeURIComponent(pkgVersion)}`, { method: "GET", signal: compositeSignal, headers: { "User-Agent": "socket-registry" } } ); if (response.ok) { return getProvenanceDetails(await response.json()); } } catch { } return void 0; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { fetchPackageProvenance, getProvenanceDetails });