@socketsecurity/lib 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.2] - 2025-10-23
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fixed broken relative import paths in `packages/isolation.ts` and `packages/provenance.ts` that prevented bundling by external tools
|
|
13
|
+
|
|
8
14
|
## [1.1.1] - 2025-10-23
|
|
9
15
|
|
|
10
16
|
### Fixed
|
|
@@ -126,7 +126,7 @@ async function isolatePackage(packageSpec, options) {
|
|
|
126
126
|
await install(packageTempDir);
|
|
127
127
|
} else {
|
|
128
128
|
const { spawn } = require("../spawn");
|
|
129
|
-
const WIN322 = require("
|
|
129
|
+
const WIN322 = require("../constants/platform").WIN32;
|
|
130
130
|
const packageInstallSpec = spec.startsWith("https://") ? spec : `${packageName}@${spec}`;
|
|
131
131
|
await spawn("pnpm", ["add", packageInstallSpec], {
|
|
132
132
|
cwd: packageTempDir,
|
|
@@ -171,7 +171,7 @@ async function isolatePackage(packageSpec, options) {
|
|
|
171
171
|
await install(installedPath);
|
|
172
172
|
} else {
|
|
173
173
|
const { spawn } = require("../spawn");
|
|
174
|
-
const WIN322 = require("
|
|
174
|
+
const WIN322 = require("../constants/platform").WIN32;
|
|
175
175
|
await spawn("pnpm", ["install"], {
|
|
176
176
|
cwd: installedPath,
|
|
177
177
|
shell: WIN322,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/packages/isolation.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @fileoverview Package isolation utilities for testing.\n * Provides tools to set up isolated test environments for packages.\n */\n\nimport { existsSync, promises as fs } from 'node:fs'\n\nimport { WIN32 } from '#constants/platform'\n\nimport type { PackageJson } from '../packages'\nimport { isAbsolute, isPath, trimLeadingDotSlash } from '../path'\nimport { readPackageJson } from './operations'\n\nlet _os: typeof import('node:os') | undefined\nlet _path: typeof import('node:path') | undefined\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction getOs() {\n if (_os === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _os = /*@__PURE__*/ require('node:os')\n }\n return _os as typeof import('node:os')\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPath() {\n if (_path === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _path = /*@__PURE__*/ require('node:path')\n }\n return _path as typeof import('path')\n}\n\n/**\n * Copy options for fs.cp with cross-platform retry support.\n */\nconst FS_CP_OPTIONS = {\n dereference: true,\n errorOnExist: false,\n filter: (src: string) =>\n !src.includes('node_modules') && !src.endsWith('.DS_Store'),\n force: true,\n recursive: true,\n ...(WIN32 ? { maxRetries: 3, retryDelay: 100 } : {}),\n}\n\n/**\n * Resolve a path to its real location, handling symlinks.\n */\nasync function resolveRealPath(pathStr: string): Promise<string> {\n const path = getPath()\n return await fs.realpath(pathStr).catch(() => path.resolve(pathStr))\n}\n\n/**\n * Merge and write package.json with original and new values.\n */\nasync function mergePackageJson(\n pkgJsonPath: string,\n originalPkgJson: PackageJson | undefined,\n): Promise<PackageJson> {\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'))\n const mergedPkgJson = originalPkgJson\n ? { ...originalPkgJson, ...pkgJson }\n : pkgJson\n return mergedPkgJson\n}\n\nexport type IsolatePackageOptions = {\n imports?: Record<string, string> | undefined\n install?: ((cwd: string) => Promise<void>) | undefined\n onPackageJson?:\n | ((pkgJson: PackageJson) => PackageJson | Promise<PackageJson>)\n | undefined\n sourcePath?: string | undefined\n}\n\nexport type IsolatePackageResult = {\n exports?: Record<string, unknown> | undefined\n tmpdir: string\n}\n\n/**\n * Isolates a package in a temporary test environment.\n *\n * Supports multiple input types:\n * 1. File system path (absolute or relative)\n * 2. Package name with optional version spec\n * 3. npm package spec (parsed via npm-package-arg)\n *\n * @throws {Error} When package installation or setup fails.\n */\nexport async function isolatePackage(\n packageSpec: string,\n options?: IsolatePackageOptions | undefined,\n): Promise<IsolatePackageResult> {\n const os = getOs()\n const path = getPath()\n const opts = { __proto__: null, ...options } as IsolatePackageOptions\n const { imports, install, onPackageJson, sourcePath: optSourcePath } = opts\n\n let sourcePath = optSourcePath\n let packageName: string | undefined\n let spec: string | undefined\n\n // Determine if this is a path or package spec.\n if (isPath(packageSpec)) {\n // File system path.\n // Handle edge case on Windows where path.relative() returns an absolute path\n // when paths are on different drives, and the test prepends './' to it.\n // Example: './C:\\Users\\...' should be treated as 'C:\\Users\\...'.\n const trimmedPath = trimLeadingDotSlash(packageSpec)\n const pathToResolve = isAbsolute(trimmedPath) ? trimmedPath : packageSpec\n sourcePath = path.resolve(pathToResolve)\n\n if (!existsSync(sourcePath)) {\n throw new Error(`Source path does not exist: ${sourcePath}`)\n }\n\n // Read package.json to get the name.\n const pkgJson = await readPackageJson(sourcePath, { normalize: true })\n if (!pkgJson) {\n throw new Error(`Could not read package.json from: ${sourcePath}`)\n }\n packageName = pkgJson.name as string\n } else {\n // Parse as npm package spec.\n const npa = /*@__PURE__*/ require('../external/npm-package-arg')\n const parsed = npa(packageSpec)\n\n packageName = parsed.name\n\n if (parsed.type === 'directory' || parsed.type === 'file') {\n sourcePath = parsed.fetchSpec\n if (!sourcePath || !existsSync(sourcePath)) {\n throw new Error(`Source path does not exist: ${sourcePath}`)\n }\n // If package name not provided by parser, read from package.json.\n if (!packageName) {\n const pkgJson = await readPackageJson(sourcePath, { normalize: true })\n if (!pkgJson) {\n throw new Error(`Could not read package.json from: ${sourcePath}`)\n }\n packageName = pkgJson.name as string\n }\n } else {\n // Registry package.\n spec = parsed.fetchSpec || parsed.rawSpec\n }\n }\n\n if (!packageName) {\n throw new Error(`Could not determine package name from: ${packageSpec}`)\n }\n\n // Create temp directory for this package.\n const sanitizedName = packageName.replace(/[@/]/g, '-')\n const tempDir = await fs.mkdtemp(\n path.join(os.tmpdir(), `socket-test-${sanitizedName}-`),\n )\n const packageTempDir = path.join(tempDir, sanitizedName)\n await fs.mkdir(packageTempDir, { recursive: true })\n\n let installedPath: string\n let originalPackageJson: PackageJson | undefined\n\n if (spec) {\n // Installing from registry first, then copying source on top if provided.\n await fs.writeFile(\n path.join(packageTempDir, 'package.json'),\n JSON.stringify(\n {\n name: 'test-temp',\n private: true,\n version: '1.0.0',\n },\n null,\n 2,\n ),\n )\n\n // Use custom install function or default pnpm install.\n if (install) {\n await install(packageTempDir)\n } else {\n const { spawn } = /*@__PURE__*/ require('../spawn')\n const WIN32 = require('
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * @fileoverview Package isolation utilities for testing.\n * Provides tools to set up isolated test environments for packages.\n */\n\nimport { existsSync, promises as fs } from 'node:fs'\n\nimport { WIN32 } from '#constants/platform'\n\nimport type { PackageJson } from '../packages'\nimport { isAbsolute, isPath, trimLeadingDotSlash } from '../path'\nimport { readPackageJson } from './operations'\n\nlet _os: typeof import('node:os') | undefined\nlet _path: typeof import('node:path') | undefined\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction getOs() {\n if (_os === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _os = /*@__PURE__*/ require('node:os')\n }\n return _os as typeof import('node:os')\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction getPath() {\n if (_path === undefined) {\n // Use non-'node:' prefixed require to avoid Webpack errors.\n\n _path = /*@__PURE__*/ require('node:path')\n }\n return _path as typeof import('path')\n}\n\n/**\n * Copy options for fs.cp with cross-platform retry support.\n */\nconst FS_CP_OPTIONS = {\n dereference: true,\n errorOnExist: false,\n filter: (src: string) =>\n !src.includes('node_modules') && !src.endsWith('.DS_Store'),\n force: true,\n recursive: true,\n ...(WIN32 ? { maxRetries: 3, retryDelay: 100 } : {}),\n}\n\n/**\n * Resolve a path to its real location, handling symlinks.\n */\nasync function resolveRealPath(pathStr: string): Promise<string> {\n const path = getPath()\n return await fs.realpath(pathStr).catch(() => path.resolve(pathStr))\n}\n\n/**\n * Merge and write package.json with original and new values.\n */\nasync function mergePackageJson(\n pkgJsonPath: string,\n originalPkgJson: PackageJson | undefined,\n): Promise<PackageJson> {\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'))\n const mergedPkgJson = originalPkgJson\n ? { ...originalPkgJson, ...pkgJson }\n : pkgJson\n return mergedPkgJson\n}\n\nexport type IsolatePackageOptions = {\n imports?: Record<string, string> | undefined\n install?: ((cwd: string) => Promise<void>) | undefined\n onPackageJson?:\n | ((pkgJson: PackageJson) => PackageJson | Promise<PackageJson>)\n | undefined\n sourcePath?: string | undefined\n}\n\nexport type IsolatePackageResult = {\n exports?: Record<string, unknown> | undefined\n tmpdir: string\n}\n\n/**\n * Isolates a package in a temporary test environment.\n *\n * Supports multiple input types:\n * 1. File system path (absolute or relative)\n * 2. Package name with optional version spec\n * 3. npm package spec (parsed via npm-package-arg)\n *\n * @throws {Error} When package installation or setup fails.\n */\nexport async function isolatePackage(\n packageSpec: string,\n options?: IsolatePackageOptions | undefined,\n): Promise<IsolatePackageResult> {\n const os = getOs()\n const path = getPath()\n const opts = { __proto__: null, ...options } as IsolatePackageOptions\n const { imports, install, onPackageJson, sourcePath: optSourcePath } = opts\n\n let sourcePath = optSourcePath\n let packageName: string | undefined\n let spec: string | undefined\n\n // Determine if this is a path or package spec.\n if (isPath(packageSpec)) {\n // File system path.\n // Handle edge case on Windows where path.relative() returns an absolute path\n // when paths are on different drives, and the test prepends './' to it.\n // Example: './C:\\Users\\...' should be treated as 'C:\\Users\\...'.\n const trimmedPath = trimLeadingDotSlash(packageSpec)\n const pathToResolve = isAbsolute(trimmedPath) ? trimmedPath : packageSpec\n sourcePath = path.resolve(pathToResolve)\n\n if (!existsSync(sourcePath)) {\n throw new Error(`Source path does not exist: ${sourcePath}`)\n }\n\n // Read package.json to get the name.\n const pkgJson = await readPackageJson(sourcePath, { normalize: true })\n if (!pkgJson) {\n throw new Error(`Could not read package.json from: ${sourcePath}`)\n }\n packageName = pkgJson.name as string\n } else {\n // Parse as npm package spec.\n const npa = /*@__PURE__*/ require('../external/npm-package-arg')\n const parsed = npa(packageSpec)\n\n packageName = parsed.name\n\n if (parsed.type === 'directory' || parsed.type === 'file') {\n sourcePath = parsed.fetchSpec\n if (!sourcePath || !existsSync(sourcePath)) {\n throw new Error(`Source path does not exist: ${sourcePath}`)\n }\n // If package name not provided by parser, read from package.json.\n if (!packageName) {\n const pkgJson = await readPackageJson(sourcePath, { normalize: true })\n if (!pkgJson) {\n throw new Error(`Could not read package.json from: ${sourcePath}`)\n }\n packageName = pkgJson.name as string\n }\n } else {\n // Registry package.\n spec = parsed.fetchSpec || parsed.rawSpec\n }\n }\n\n if (!packageName) {\n throw new Error(`Could not determine package name from: ${packageSpec}`)\n }\n\n // Create temp directory for this package.\n const sanitizedName = packageName.replace(/[@/]/g, '-')\n const tempDir = await fs.mkdtemp(\n path.join(os.tmpdir(), `socket-test-${sanitizedName}-`),\n )\n const packageTempDir = path.join(tempDir, sanitizedName)\n await fs.mkdir(packageTempDir, { recursive: true })\n\n let installedPath: string\n let originalPackageJson: PackageJson | undefined\n\n if (spec) {\n // Installing from registry first, then copying source on top if provided.\n await fs.writeFile(\n path.join(packageTempDir, 'package.json'),\n JSON.stringify(\n {\n name: 'test-temp',\n private: true,\n version: '1.0.0',\n },\n null,\n 2,\n ),\n )\n\n // Use custom install function or default pnpm install.\n if (install) {\n await install(packageTempDir)\n } else {\n const { spawn } = /*@__PURE__*/ require('../spawn')\n const WIN32 = require('../constants/platform').WIN32\n const packageInstallSpec = spec.startsWith('https://')\n ? spec\n : `${packageName}@${spec}`\n\n await spawn('pnpm', ['add', packageInstallSpec], {\n cwd: packageTempDir,\n shell: WIN32,\n stdio: 'pipe',\n })\n }\n\n installedPath = path.join(packageTempDir, 'node_modules', packageName)\n\n // Save original package.json before copying source.\n originalPackageJson = await readPackageJson(installedPath, {\n normalize: true,\n })\n\n // Copy source files on top if provided.\n if (sourcePath) {\n // Check if source and destination are the same (symlinked).\n const realInstalledPath = await resolveRealPath(installedPath)\n const realSourcePath = await resolveRealPath(sourcePath)\n\n if (realSourcePath !== realInstalledPath) {\n await fs.cp(sourcePath, installedPath, FS_CP_OPTIONS)\n }\n }\n } else {\n // Just copying local package, no registry install.\n if (!sourcePath) {\n throw new Error('sourcePath is required when no version spec provided')\n }\n\n const scopedPath = packageName.startsWith('@')\n ? path.join(\n packageTempDir,\n 'node_modules',\n packageName.split('/')[0] ?? '',\n )\n : path.join(packageTempDir, 'node_modules')\n\n await fs.mkdir(scopedPath, { recursive: true })\n installedPath = path.join(packageTempDir, 'node_modules', packageName)\n\n await fs.cp(sourcePath, installedPath, FS_CP_OPTIONS)\n }\n\n // Prepare package.json if callback provided or if we need to merge with original.\n if (onPackageJson || originalPackageJson) {\n const pkgJsonPath = path.join(installedPath, 'package.json')\n const mergedPkgJson = await mergePackageJson(\n pkgJsonPath,\n originalPackageJson,\n )\n\n const finalPkgJson = onPackageJson\n ? await onPackageJson(mergedPkgJson)\n : mergedPkgJson\n\n await fs.writeFile(pkgJsonPath, JSON.stringify(finalPkgJson, null, 2))\n }\n\n // Install dependencies.\n if (install) {\n await install(installedPath)\n } else {\n const { spawn } = /*@__PURE__*/ require('../spawn')\n const WIN32 = require('../constants/platform').WIN32\n await spawn('pnpm', ['install'], {\n cwd: installedPath,\n shell: WIN32,\n stdio: 'pipe',\n })\n }\n\n // Load module exports if imports provided.\n const exports: Record<string, unknown> = imports\n ? { __proto__: null }\n : (undefined as unknown as Record<string, unknown>)\n\n if (imports) {\n for (const { 0: key, 1: specifier } of Object.entries(imports)) {\n const fullPath = path.join(installedPath, specifier)\n exports[key] = require(fullPath)\n }\n }\n\n return {\n exports,\n tmpdir: installedPath,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["fs", "WIN32", "exports"]
|
|
7
7
|
}
|
|
@@ -33,7 +33,7 @@ let _fetcher;
|
|
|
33
33
|
function getFetcher() {
|
|
34
34
|
if (_fetcher === void 0) {
|
|
35
35
|
const makeFetchHappen = require("../external/make-fetch-happen");
|
|
36
|
-
const { getPacoteCachePath } = require("
|
|
36
|
+
const { getPacoteCachePath } = require("../constants/packages");
|
|
37
37
|
_fetcher = makeFetchHappen.defaults({
|
|
38
38
|
cachePath: getPacoteCachePath(),
|
|
39
39
|
// Prefer-offline: Staleness checks for cached data will be bypassed, but
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/packages/provenance.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @fileoverview Package provenance and attestation verification utilities.\n */\n\nimport { NPM_REGISTRY_URL } from '#constants/agents'\n\nimport { createCompositeAbortSignal, createTimeoutSignal } from '../abort'\nimport type { ProvenanceOptions } from '../packages'\nimport { parseUrl } from '../url'\n\n// IMPORTANT: Do not use destructuring here - use direct assignment instead.\n// tsgo has a bug that incorrectly transpiles destructured exports, resulting in\n// `exports.SomeName = void 0;` which causes runtime errors.\n// See: https://github.com/SocketDev/socket-packageurl-js/issues/3\nconst ArrayIsArray = Array.isArray\n\nconst SLSA_PROVENANCE_V0_2 = 'https://slsa.dev/provenance/v0.2'\nconst SLSA_PROVENANCE_V1_0 = 'https://slsa.dev/provenance/v1'\n\nlet _fetcher: typeof import('make-fetch-happen') | undefined\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFetcher() {\n if (_fetcher === undefined) {\n const makeFetchHappen =\n /*@__PURE__*/ require('../external/make-fetch-happen')\n // Lazy load constants to avoid circular dependencies.\n const { getPacoteCachePath } =\n /*@__PURE__*/ require('
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,oBAAiC;AAEjC,mBAAgE;AAEhE,iBAAyB;AAMzB,MAAM,eAAe,MAAM;AAE3B,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAE7B,IAAI;AAAA;AAEJ,SAAS,aAAa;AACpB,MAAI,aAAa,QAAW;AAC1B,UAAM,kBACU,QAAQ,+BAA+B;AAEvD,UAAM,EAAE,mBAAmB,IACX,QAAQ,
|
|
4
|
+
"sourcesContent": ["/**\n * @fileoverview Package provenance and attestation verification utilities.\n */\n\nimport { NPM_REGISTRY_URL } from '#constants/agents'\n\nimport { createCompositeAbortSignal, createTimeoutSignal } from '../abort'\nimport type { ProvenanceOptions } from '../packages'\nimport { parseUrl } from '../url'\n\n// IMPORTANT: Do not use destructuring here - use direct assignment instead.\n// tsgo has a bug that incorrectly transpiles destructured exports, resulting in\n// `exports.SomeName = void 0;` which causes runtime errors.\n// See: https://github.com/SocketDev/socket-packageurl-js/issues/3\nconst ArrayIsArray = Array.isArray\n\nconst SLSA_PROVENANCE_V0_2 = 'https://slsa.dev/provenance/v0.2'\nconst SLSA_PROVENANCE_V1_0 = 'https://slsa.dev/provenance/v1'\n\nlet _fetcher: typeof import('make-fetch-happen') | undefined\n/*@__NO_SIDE_EFFECTS__*/\nfunction getFetcher() {\n if (_fetcher === undefined) {\n const makeFetchHappen =\n /*@__PURE__*/ require('../external/make-fetch-happen')\n // Lazy load constants to avoid circular dependencies.\n const { getPacoteCachePath } =\n /*@__PURE__*/ require('../constants/packages')\n _fetcher = makeFetchHappen.defaults({\n cachePath: getPacoteCachePath(),\n // Prefer-offline: Staleness checks for cached data will be bypassed, but\n // missing data will be requested from the server.\n // https://github.com/npm/make-fetch-happen?tab=readme-ov-file#--optscache\n cache: 'force-cache',\n })\n }\n return _fetcher as typeof import('make-fetch-happen')\n}\n\n/**\n * Extract and filter SLSA provenance attestations from attestation data.\n */\nfunction getAttestations(attestationData: unknown): unknown[] {\n const data = attestationData as { attestations?: unknown[] }\n if (!data.attestations || !ArrayIsArray(data.attestations)) {\n return []\n }\n\n return data.attestations.filter((attestation: unknown) => {\n const att = attestation as { predicateType?: string }\n return (\n att.predicateType === SLSA_PROVENANCE_V0_2 ||\n att.predicateType === SLSA_PROVENANCE_V1_0\n )\n })\n}\n\n/**\n * Find the first attestation with valid provenance data.\n */\nfunction findProvenance(attestations: unknown[]): unknown {\n for (const attestation of attestations) {\n const att = attestation as {\n bundle?: { dsseEnvelope?: { payload?: string } }\n predicate?: unknown\n }\n try {\n let predicate = att.predicate\n\n // If predicate is not directly available, try to decode from DSSE envelope\n if (!predicate && att.bundle?.dsseEnvelope?.payload) {\n try {\n const decodedPayload = Buffer.from(\n att.bundle.dsseEnvelope.payload,\n 'base64',\n ).toString('utf8')\n const statement = JSON.parse(decodedPayload)\n predicate = statement.predicate\n } catch {\n // Failed to decode, continue to next attestation\n continue\n }\n }\n\n const predicateData = predicate as {\n buildDefinition?: { externalParameters?: unknown }\n }\n if (predicateData?.buildDefinition?.externalParameters) {\n return {\n predicate,\n externalParameters: predicateData.buildDefinition.externalParameters,\n }\n }\n // c8 ignore start - Error handling for malformed attestation data should continue processing other attestations.\n } catch {\n // Continue checking other attestations if one fails to parse\n }\n // c8 ignore stop\n }\n return undefined\n}\n\n/**\n * Check if a value indicates a trusted publisher (GitHub or GitLab).\n */\nfunction isTrustedPublisher(value: unknown): boolean {\n if (typeof value !== 'string' || !value) {\n return false\n }\n\n let url = parseUrl(value)\n let hostname = url?.hostname\n\n // Handle GitHub workflow refs with @ syntax by trying the first part.\n // Example: \"https://github.com/owner/repo/.github/workflows/ci.yml@refs/heads/main\"\n if (!url && value.includes('@')) {\n const firstPart = value.split('@')[0]\n if (firstPart) {\n url = parseUrl(firstPart)\n }\n if (url) {\n hostname = url.hostname\n }\n }\n\n // Try common URL prefixes if not already a complete URL.\n if (!url) {\n const httpsUrl = parseUrl(`https://${value}`)\n if (httpsUrl) {\n hostname = httpsUrl.hostname\n }\n }\n\n if (hostname) {\n return (\n hostname === 'github.com' ||\n hostname.endsWith('.github.com') ||\n hostname === 'gitlab.com' ||\n hostname.endsWith('.gitlab.com')\n )\n }\n\n // Fallback: check for provider keywords in non-URL strings.\n return value.includes('github') || value.includes('gitlab')\n}\n\n/**\n * Convert raw attestation data to user-friendly provenance details.\n */\nexport function getProvenanceDetails(attestationData: unknown): unknown {\n const attestations = getAttestations(attestationData)\n if (!attestations.length) {\n return undefined\n }\n // Find the first attestation with valid provenance data.\n const provenance = findProvenance(attestations)\n if (!provenance) {\n return { level: 'attested' }\n }\n\n const provenanceData = provenance as {\n externalParameters?: {\n context?: string\n ref?: string\n repository?: string\n run_id?: string\n sha?: string\n workflow?: {\n ref?: string\n repository?: string\n }\n workflow_ref?: string\n }\n predicate?: {\n buildDefinition?: { buildType?: string }\n }\n }\n const { externalParameters, predicate } = provenanceData\n const def = predicate?.buildDefinition\n\n // Handle both SLSA v0.2 (direct properties) and v1 (nested workflow object)\n const workflow = externalParameters?.workflow\n const workflowRef = workflow?.ref || externalParameters?.workflow_ref\n const workflowUrl = externalParameters?.context\n const workflowPlatform = def?.buildType\n const repository = workflow?.repository || externalParameters?.repository\n const gitRef = externalParameters?.ref || workflow?.ref\n const commitSha = externalParameters?.sha\n const workflowRunId = externalParameters?.run_id\n\n // Check for trusted publishers (GitHub Actions, GitLab CI/CD).\n const trusted =\n isTrustedPublisher(workflowRef) ||\n isTrustedPublisher(workflowUrl) ||\n isTrustedPublisher(workflowPlatform) ||\n isTrustedPublisher(repository)\n\n return {\n commitSha,\n gitRef,\n level: trusted ? 'trusted' : 'attested',\n repository,\n workflowRef,\n workflowUrl,\n workflowPlatform,\n workflowRunId,\n }\n}\n\n/**\n * Fetch package provenance information from npm registry.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport async function fetchPackageProvenance(\n pkgName: string,\n pkgVersion: string,\n options?: ProvenanceOptions,\n): Promise<unknown> {\n const { signal, timeout = 10_000 } = {\n __proto__: null,\n ...options,\n } as ProvenanceOptions\n\n if (signal?.aborted) {\n return undefined\n }\n\n // Create composite signal combining external signal with timeout\n const timeoutSignal = createTimeoutSignal(timeout)\n const compositeSignal = createCompositeAbortSignal(signal, timeoutSignal)\n const fetcher = getFetcher()\n\n try {\n const response = await fetcher(\n // The npm registry attestations API endpoint.\n `${NPM_REGISTRY_URL}/-/npm/v1/attestations/${encodeURIComponent(pkgName)}@${encodeURIComponent(pkgVersion)}`,\n {\n method: 'GET',\n signal: compositeSignal,\n headers: {\n 'User-Agent': 'socket-registry',\n },\n } as {\n method: string\n signal: AbortSignal\n headers: Record<string, string>\n },\n )\n if (response.ok) {\n return getProvenanceDetails(await response.json())\n }\n } catch {}\n return undefined\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|