@socketsecurity/lib
Version:
Core utilities and infrastructure for Socket.dev security tools
181 lines (180 loc) • 6.14 kB
JavaScript
;
/* 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
});