@socketsecurity/lib
Version:
Core utilities and infrastructure for Socket.dev security tools
429 lines (428 loc) • 14.3 kB
JavaScript
;
/* Socket Lib - Built with esbuild */
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var dlx_binary_exports = {};
__export(dlx_binary_exports, {
cleanDlxCache: () => cleanDlxCache,
dlxBinary: () => dlxBinary,
downloadBinary: () => downloadBinary,
executeBinary: () => executeBinary,
getDlxCachePath: () => getDlxCachePath,
listDlxCache: () => listDlxCache
});
module.exports = __toCommonJS(dlx_binary_exports);
var import_crypto = require("crypto");
var import_os = __toESM(require("os"));
var import_path = __toESM(require("path"));
var import_platform = require("#constants/platform");
var import_dlx = require("./dlx");
var import_dlx_manifest = require("./dlx-manifest");
var import_http_request = require("./http-request");
var import_fs = require("./fs");
var import_objects = require("./objects");
var import_path2 = require("./path");
var import_paths = require("./paths");
var import_process_lock = require("./process-lock");
var import_spawn = require("./spawn");
let _fs;
// @__NO_SIDE_EFFECTS__
function getFs() {
if (_fs === void 0) {
_fs = require("node:fs");
}
return _fs;
}
function getMetadataPath(cacheEntryPath) {
return import_path.default.join(cacheEntryPath, ".dlx-metadata.json");
}
async function isCacheValid(cacheEntryPath, cacheTtl) {
const fs = /* @__PURE__ */ getFs();
try {
const metaPath = getMetadataPath(cacheEntryPath);
if (!fs.existsSync(metaPath)) {
return false;
}
const metadata = await (0, import_fs.readJson)(metaPath, { throws: false });
if (!(0, import_objects.isObjectObject)(metadata)) {
return false;
}
const now = Date.now();
const timestamp = metadata["timestamp"];
if (typeof timestamp !== "number" || timestamp <= 0) {
return false;
}
const age = now - timestamp;
return age < cacheTtl;
} catch {
return false;
}
}
async function downloadBinaryFile(url, destPath, checksum) {
const cacheEntryDir = import_path.default.dirname(destPath);
const lockPath = import_path.default.join(cacheEntryDir, "concurrency.lock");
return await import_process_lock.processLock.withLock(
lockPath,
async () => {
const fs = /* @__PURE__ */ getFs();
if (fs.existsSync(destPath)) {
const stats = await fs.promises.stat(destPath);
if (stats.size > 0) {
const fileBuffer2 = await fs.promises.readFile(destPath);
const hasher2 = (0, import_crypto.createHash)("sha256");
hasher2.update(fileBuffer2);
return hasher2.digest("hex");
}
}
try {
await (0, import_http_request.httpDownload)(url, destPath);
} catch (e) {
throw new Error(
`Failed to download binary from ${url}
Destination: ${destPath}
Check your internet connection or verify the URL is accessible.`,
{ cause: e }
);
}
const fileBuffer = await fs.promises.readFile(destPath);
const hasher = (0, import_crypto.createHash)("sha256");
hasher.update(fileBuffer);
const actualChecksum = hasher.digest("hex");
if (checksum && actualChecksum !== checksum) {
await (0, import_fs.safeDelete)(destPath);
throw new Error(
`Checksum mismatch: expected ${checksum}, got ${actualChecksum}`
);
}
if (!import_platform.WIN32) {
await fs.promises.chmod(destPath, 493);
}
return actualChecksum;
},
{
// Align with npm npx locking strategy.
staleMs: 5e3,
touchIntervalMs: 2e3
}
);
}
async function writeMetadata(cacheEntryPath, cacheKey, url, binaryName, checksum, size) {
const metaPath = getMetadataPath(cacheEntryPath);
const metadata = {
version: "1.0.0",
cache_key: cacheKey,
timestamp: Date.now(),
checksum,
checksum_algorithm: "sha256",
platform: import_os.default.platform(),
arch: import_os.default.arch(),
size,
source: {
type: "download",
url
}
};
const fs = /* @__PURE__ */ getFs();
await fs.promises.writeFile(metaPath, JSON.stringify(metadata, null, 2));
try {
const spec = `${url}:${binaryName}`;
await import_dlx_manifest.dlxManifest.setBinaryEntry(spec, cacheKey, {
checksum,
checksum_algorithm: "sha256",
platform: import_os.default.platform(),
arch: import_os.default.arch(),
size,
source: {
type: "download",
url
}
});
} catch {
}
}
async function cleanDlxCache(maxAge = (
/*@__INLINE__*/
require("#constants/time").DLX_BINARY_CACHE_TTL
)) {
const cacheDir = getDlxCachePath();
const fs = /* @__PURE__ */ getFs();
if (!fs.existsSync(cacheDir)) {
return 0;
}
let cleaned = 0;
const now = Date.now();
const entries = await fs.promises.readdir(cacheDir);
for (const entry of entries) {
const entryPath = import_path.default.join(cacheDir, entry);
const metaPath = getMetadataPath(entryPath);
try {
if (!await (0, import_fs.isDir)(entryPath)) {
continue;
}
const metadata = await (0, import_fs.readJson)(metaPath, { throws: false });
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
continue;
}
const timestamp = metadata["timestamp"];
const age = typeof timestamp === "number" && timestamp > 0 ? now - timestamp : Number.POSITIVE_INFINITY;
if (age > maxAge) {
await (0, import_fs.safeDelete)(entryPath, { force: true, recursive: true });
cleaned += 1;
}
} catch {
try {
const contents = await fs.promises.readdir(entryPath);
if (!contents.length) {
await (0, import_fs.safeDelete)(entryPath);
cleaned += 1;
}
} catch {
}
}
}
return cleaned;
}
async function dlxBinary(args, options, spawnExtra) {
const {
cacheTtl = (
/*@__INLINE__*/
require("#constants/time").DLX_BINARY_CACHE_TTL
),
checksum,
force: userForce = false,
name,
spawnOptions,
url,
yes
} = { __proto__: null, ...options };
const force = yes === true ? true : userForce;
const cacheDir = getDlxCachePath();
const binaryName = name || `binary-${process.platform}-${import_os.default.arch()}`;
const spec = `${url}:${binaryName}`;
const cacheKey = (0, import_dlx.generateCacheKey)(spec);
const cacheEntryDir = import_path.default.join(cacheDir, cacheKey);
const binaryPath = (0, import_path2.normalizePath)(import_path.default.join(cacheEntryDir, binaryName));
const fs = /* @__PURE__ */ getFs();
let downloaded = false;
let computedChecksum = checksum;
if (!force && fs.existsSync(cacheEntryDir) && await isCacheValid(cacheEntryDir, cacheTtl)) {
try {
const metaPath = getMetadataPath(cacheEntryDir);
const metadata = await (0, import_fs.readJson)(metaPath, { throws: false });
if (metadata && typeof metadata === "object" && !Array.isArray(metadata) && typeof metadata["checksum"] === "string") {
computedChecksum = metadata["checksum"];
} else {
downloaded = true;
}
} catch {
downloaded = true;
}
} else {
downloaded = true;
}
if (downloaded) {
try {
await (0, import_fs.safeMkdir)(cacheEntryDir);
} catch (e) {
const code = e.code;
if (code === "EACCES" || code === "EPERM") {
throw new Error(
`Permission denied creating binary cache directory: ${cacheEntryDir}
Please check directory permissions or run with appropriate access.`,
{ cause: e }
);
}
if (code === "EROFS") {
throw new Error(
`Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir}
Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`,
{ cause: e }
);
}
throw new Error(
`Failed to create binary cache directory: ${cacheEntryDir}`,
{ cause: e }
);
}
computedChecksum = await downloadBinaryFile(url, binaryPath, checksum);
const stats = await fs.promises.stat(binaryPath);
await writeMetadata(
cacheEntryDir,
cacheKey,
url,
binaryName,
computedChecksum || "",
stats.size
);
}
const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath);
const finalSpawnOptions = needsShell ? {
...spawnOptions,
env: {
...spawnOptions?.env,
PATH: `${cacheEntryDir}${import_path.default.delimiter}${process.env["PATH"] || ""}`
},
shell: true
} : spawnOptions;
const spawnPromise = (0, import_spawn.spawn)(binaryPath, args, finalSpawnOptions, spawnExtra);
return {
binaryPath,
downloaded,
spawnPromise
};
}
async function downloadBinary(options) {
const {
cacheTtl = (
/*@__INLINE__*/
require("#constants/time").DLX_BINARY_CACHE_TTL
),
checksum,
force = false,
name,
url
} = { __proto__: null, ...options };
const cacheDir = getDlxCachePath();
const binaryName = name || `binary-${process.platform}-${import_os.default.arch()}`;
const spec = `${url}:${binaryName}`;
const cacheKey = (0, import_dlx.generateCacheKey)(spec);
const cacheEntryDir = import_path.default.join(cacheDir, cacheKey);
const binaryPath = (0, import_path2.normalizePath)(import_path.default.join(cacheEntryDir, binaryName));
const fs = /* @__PURE__ */ getFs();
let downloaded = false;
if (!force && fs.existsSync(cacheEntryDir) && await isCacheValid(cacheEntryDir, cacheTtl)) {
downloaded = false;
} else {
try {
await (0, import_fs.safeMkdir)(cacheEntryDir);
} catch (e) {
const code = e.code;
if (code === "EACCES" || code === "EPERM") {
throw new Error(
`Permission denied creating binary cache directory: ${cacheEntryDir}
Please check directory permissions or run with appropriate access.`,
{ cause: e }
);
}
if (code === "EROFS") {
throw new Error(
`Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir}
Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`,
{ cause: e }
);
}
throw new Error(
`Failed to create binary cache directory: ${cacheEntryDir}`,
{ cause: e }
);
}
const computedChecksum = await downloadBinaryFile(url, binaryPath, checksum);
const stats = await fs.promises.stat(binaryPath);
await writeMetadata(
cacheEntryDir,
cacheKey,
url,
binaryName,
computedChecksum || "",
stats.size
);
downloaded = true;
}
return {
binaryPath,
downloaded
};
}
function executeBinary(binaryPath, args, spawnOptions, spawnExtra) {
const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath);
const cacheEntryDir = import_path.default.dirname(binaryPath);
const finalSpawnOptions = needsShell ? {
...spawnOptions,
env: {
...spawnOptions?.env,
PATH: `${cacheEntryDir}${import_path.default.delimiter}${process.env["PATH"] || ""}`
},
shell: true
} : spawnOptions;
return (0, import_spawn.spawn)(binaryPath, args, finalSpawnOptions, spawnExtra);
}
function getDlxCachePath() {
return (0, import_paths.getSocketDlxDir)();
}
async function listDlxCache() {
const cacheDir = getDlxCachePath();
const fs = /* @__PURE__ */ getFs();
if (!fs.existsSync(cacheDir)) {
return [];
}
const results = [];
const now = Date.now();
const entries = await fs.promises.readdir(cacheDir);
for (const entry of entries) {
const entryPath = import_path.default.join(cacheDir, entry);
try {
if (!await (0, import_fs.isDir)(entryPath)) {
continue;
}
const metaPath = getMetadataPath(entryPath);
const metadata = await (0, import_fs.readJson)(metaPath, { throws: false });
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
continue;
}
const metaObj = metadata;
const source = metaObj["source"];
const url = source?.["url"] || metaObj["url"] || "";
const files = await fs.promises.readdir(entryPath);
const binaryFile = files.find((f) => !f.startsWith("."));
if (binaryFile) {
const binaryPath = import_path.default.join(entryPath, binaryFile);
const binaryStats = await fs.promises.stat(binaryPath);
results.push({
age: now - (metaObj["timestamp"] || 0),
arch: metaObj["arch"] || "unknown",
checksum: metaObj["checksum"] || "",
name: binaryFile,
platform: metaObj["platform"] || "unknown",
size: binaryStats.size,
url
});
}
} catch {
}
}
return results;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
cleanDlxCache,
dlxBinary,
downloadBinary,
executeBinary,
getDlxCachePath,
listDlxCache
});