From a21d9c1fda8fa8b88ba10a035610717fee30de6e Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Thu, 16 Jul 2026 10:07:34 +0200 Subject: [PATCH 01/19] Apply `@lavamoat/harden` defaults --- .yarnrc.yml | 5 +- lavamoat/.env.ban.json | 1 + lavamoat/.runner-plugin.js | 315 +++++++++++++++++++ lavamoat/plugin-allow-scripts.js | 17 + lavamoat/scripts.loose.json | 14 + lavamoat/scripts.strict.json | 14 + package.json | 11 + yarn.lock | 512 +++++++++++++++++++++++++++++-- 8 files changed, 861 insertions(+), 28 deletions(-) create mode 100644 lavamoat/.env.ban.json create mode 100755 lavamoat/.runner-plugin.js create mode 100644 lavamoat/plugin-allow-scripts.js create mode 100644 lavamoat/scripts.loose.json create mode 100644 lavamoat/scripts.strict.json diff --git a/.yarnrc.yml b/.yarnrc.yml index b901501..53bf402 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -28,6 +28,9 @@ npmPreapprovedPackages: - '@metamask-previews/*' - '@lavamoat/*' +# Protect the runtime of calls to "yarn run" scripts using a local plugin. plugins: - path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs - spec: 'https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js' + spec: https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js + - path: ./lavamoat/plugin-allow-scripts.js + - path: ./lavamoat/.runner-plugin.js diff --git a/lavamoat/.env.ban.json b/lavamoat/.env.ban.json new file mode 100644 index 0000000..524f5af --- /dev/null +++ b/lavamoat/.env.ban.json @@ -0,0 +1 @@ +["SESSION", "SSH", "KEY", "TOKEN", "SECRET", "PASSWORD", "AUTH"] diff --git a/lavamoat/.runner-plugin.js b/lavamoat/.runner-plugin.js new file mode 100755 index 0000000..ccd7295 --- /dev/null +++ b/lavamoat/.runner-plugin.js @@ -0,0 +1,315 @@ +/** + * Yarn 4 plugin for script environment hardening. + * + * @module + */ + +/** @typedef {NonNullable} WrapScriptExecutionHook */ + +/* global makeRunScriptWrapper */ + +/** + * Yarn 4 plugin factory for wrapScriptExecution hook. + * + * @param {any} require - Yarn's require function + * @returns {{ hooks: { wrapScriptExecution: Function } }} + */ +module.exports = { + name: '@yarnpkg/plugin-runner', + factory: function (/** @type {NodeJS.Require} */ require) { + return { + hooks: { + /** @type {WrapScriptExecutionHook} */ + wrapScriptExecution: async ( + executor, + project, + locator, + scriptName, + extra, + ) => { + const path = require('node:path'); + const fs = require('node:fs'); + const workspace = project.tryWorkspaceByLocator(locator); + + if (!workspace) { + // a script is being executed outside of a workspace context, so we can't apply any custom logic + // This is the case when a postinstal is running. + + // "Do nothing" - return the original executor immediately + // without running any custom plugin logic or reading manifests. + // TODO: implement wrapping these scripts with reasonable defaults + return executor; + } + + const pkgJson = workspace.manifest.raw; + const binFolder = + extra.env.BERRY_BIN_FOLDER || `node_modules${path.sep}.bin`; + + const wrapper = makeRunScriptWrapper( + { + scriptName, + scriptPayload: extra.script, + projectRoot: extra.cwd, + pathBinMatcher: (fragment) => { + return fragment.endsWith(binFolder); + }, + customizePermissionsConfig: addMandatoryReads, + readScriptsConfig: () => { + return pkgJson.scriptsConfig; + }, + }, + { + readFileSync: fs.readFileSync, + pathJoin: path.join, + pathDelimiter: path.delimiter, + }, + ); + + const newEnv = wrapper.processEnv(extra.env); + for (const key of Object.keys(extra.env)) { + delete extra.env[key]; + } + Object.assign(extra.env, newEnv); + return executor; + }, + }, + }; + }, +}; + +/** + * @param {Record} configOptions + * @param {NodeJS.ProcessEnv} _env + */ +function addMandatoryReads(configOptions, _env) { + if (!configOptions['--permission']) { + return; + } + if (!Array.isArray(configOptions['--allow-fs-read'])) { + configOptions['--allow-fs-read'] = []; + } + if (!Array.isArray(configOptions['--allow-fs-write'])) { + configOptions['--allow-fs-write'] = []; + } + + // figure out the /tmp dir for the current platform + + const tmpdir = + process.platform === 'win32' + ? process.env.TEMP || '' // make typescript shut up + : '/tmp'; + // yarn script execution makes heavy use of temporary dirs + configOptions['--allow-fs-read'].push(tmpdir); + configOptions['--allow-fs-write'].push(tmpdir); +} +/// + +/** + * @typedef {Record} ConfigOptions + */ + +/** + * @param {MakeRunScriptWrapperOptions} param0 + * @param {MakeRunScriptWrapperIO} param1 + * @returns {MakeRunScriptWrapper} + */ +function makeRunScriptWrapper( + { + scriptName, + scriptPayload: _scriptPayload, // might be useful to read in the future + projectRoot, + pathBinMatcher, + customizePermissionsConfig, + readScriptsConfig, + }, + { readFileSync, pathJoin, pathDelimiter }, +) { + const DEFAULT_PERMISSION_KEY = '#default'; + + /** @param {string} filePath */ + function readJsonFile(filePath) { + return JSON.parse(readFileSync(filePath, 'utf8')); + } + + /** + * @param {object} opts + * @param {Record | undefined} opts.scriptsConfig + * @param {string} [opts.scriptName] + * @param {string} opts.projectRoot + */ + function readConfig({ + scriptsConfig, + scriptName = DEFAULT_PERMISSION_KEY, + projectRoot, + }) { + if (!scriptsConfig) { + return {}; + } + const configName = + scriptsConfig[scriptName] || scriptsConfig[DEFAULT_PERMISSION_KEY]; + + // config needs to be optional, because it's opt-in first and specifying a default turns it opt-out. + if (!configName) { + return {}; + } + const configPath = pathJoin(projectRoot, configName); + let conf; + try { + conf = readJsonFile(configPath); + if (typeof conf !== 'object' || conf === null) { + throw Error(`Expected an object, got ${typeof conf}`); + } + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + throw Error( + `[LavaMoat] Error loading script config file "${configPath}": ${message}`, + { cause: err }, + ); + } + return conf; + } + + /** @param {ConfigOptions} configOptions */ + function makeFlagsFromConfig(configOptions) { + return Object.entries(configOptions) + .map(([arg, value]) => { + if (typeof value === 'boolean') { + return value ? arg : ''; + } else if (Array.isArray(value)) { + return value.map((v) => `${arg}="${v}"`).join(' '); + } else { + return `${arg}="${value}"`; + } + }) + .filter(Boolean) + .join(' '); + } + + /** + * Checks the config obtained from package.json and puts it in as NODE_OPTIONS + * + * @param {string | undefined} existingOptions + * @param {ConfigOptions} configOptions + * @param {NodeJS.ProcessEnv} env + */ + function installNodeOptions(existingOptions, configOptions, env) { + if (!configOptions) { + return existingOptions || ''; + } + + customizePermissionsConfig(configOptions, env); + + const confOption = makeFlagsFromConfig(configOptions); + + return `${existingOptions || ''} ${confOption.trim()}`.trim(); + } + + /** + * Filter environment variables based on ban keywords + * + * @param {NodeJS.ProcessEnv} env + * @param {string} lavamoatDir + * @returns {NodeJS.ProcessEnv} + */ + function filterEnv(env, lavamoatDir) { + const banFilePath = pathJoin(lavamoatDir, '.env.ban.json'); + let banConfig; + + try { + banConfig = readJsonFile(banFilePath); + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + console.error( + `[LavaMoat] Warning: Failed to read .env.ban.json: ${message}.`, + ); + return env; + } + let banKeywords = []; + try { + if (Array.isArray(banConfig)) { + banKeywords.push(...banConfig); + } else { + throw Error(`Expected .env.ban.json to contain an array of keywords`); + } + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + console.error( + `[LavaMoat] Warning: Failed to read .env.ban.json: ${message}.`, + ); + return env; + } + + /** @type {NodeJS.ProcessEnv} */ + const filteredEnv = {}; + const bannedEnv = []; + banKeywords = banKeywords.map((keyword) => keyword.toLowerCase()); + for (const [key, value] of Object.entries(env)) { + if ( + !key.toLowerCase().startsWith('npm_config') && + banKeywords.some((keyword) => key.toLowerCase().includes(keyword)) + ) { + bannedEnv.push(key); + } else { + filteredEnv[key] = value; + } + } + if (bannedEnv.length > 0) { + console.error( + `[LavaMoat] Warning: The following environment variables were banned: ${bannedEnv.join(', ')}`, + ); + } + return filteredEnv; + } + + /** @param {string} PATH */ + function envPathOpinions(PATH) { + const pathFragments = PATH.split(pathDelimiter); + // This is to eliminate bin confusion attacks. + // Find node_modules/.bin and remove it, put it on the end that gets looked up last when looking for a name in the path. + + /** @type {string[]} */ + const filteredFragments = []; + /** @type {string[]} */ + const nodeModulesBinFragments = []; + + for (const fragment of pathFragments) { + if (pathBinMatcher(fragment)) { + nodeModulesBinFragments.push(fragment); + } else { + filteredFragments.push(fragment); + } + } + // Why would there be multiple bin fragments? In a npm workspace, local bin and workspace root bin is added + filteredFragments.push(...nodeModulesBinFragments); + return filteredFragments.join(pathDelimiter); + } + + return { + processEnv: (existingEnv) => { + const scriptsConfig = readScriptsConfig(projectRoot); + const config = readConfig({ + scriptsConfig, + scriptName, + projectRoot, + }); + + // Smell: Windows environment variables are case-insensitive, but Node's process.env + // might expose it as 'Path' instead of 'PATH'. Checking both ensures it doesn't get wiped out. + + const existingPath = existingEnv.PATH || existingEnv.Path || ''; + + const lavamoatDir = pathJoin(projectRoot, 'lavamoat'); + + const fixedEnv = { + ...filterEnv(existingEnv, lavamoatDir), + PATH: envPathOpinions(existingPath), + NODE_OPTIONS: installNodeOptions( + existingEnv.NODE_OPTIONS, + config.nodeOptions, + existingEnv, + ), + }; + return fixedEnv; + }, + }; +} diff --git a/lavamoat/plugin-allow-scripts.js b/lavamoat/plugin-allow-scripts.js new file mode 100644 index 0000000..fbd0f01 --- /dev/null +++ b/lavamoat/plugin-allow-scripts.js @@ -0,0 +1,17 @@ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-allow-scripts", +factory: function (/** @type {(arg0: string) => { execute: any; }} */ require) { + const { execute } = require(`@yarnpkg/shell`); + return { + hooks: { + afterAllInstalled: async () => { + const exitCode = await execute('yarn run allow-scripts') + if (exitCode !== 0) { + process.exit(exitCode) + } + }, + }, + } + } +}; diff --git a/lavamoat/scripts.loose.json b/lavamoat/scripts.loose.json new file mode 100644 index 0000000..58cf05b --- /dev/null +++ b/lavamoat/scripts.loose.json @@ -0,0 +1,14 @@ +{ + "notes": "Should prevent basic malicious behavior of writing to locations outside the project and sending network requests, but not break any of the advanced packages in use. Everything below the net permission can be used to bypass the restrictions by a more sophisticated attacker.", + "nodeOptions": { + "--permission": true, + "--allow-fs-read": ["/"], + "--allow-fs-write": ["./"], + "--allow-net": false, + "--allow-child-process": true, + "--allow-worker": true, + "--allow-addons": true, + "--allow-wasi": true, + "--allow-inspector": false + } +} diff --git a/lavamoat/scripts.strict.json b/lavamoat/scripts.strict.json new file mode 100644 index 0000000..40a8159 --- /dev/null +++ b/lavamoat/scripts.strict.json @@ -0,0 +1,14 @@ +{ + "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit.", + "nodeOptions": { + "--permission": true, + "--allow-fs-read": ["./"], + "--allow-fs-write": ["./"], + "--allow-child-process": false, + "--allow-net": false, + "--allow-worker": false, + "--allow-addons": false, + "--allow-wasi": false, + "--allow-inspector": false + } +} diff --git a/package.json b/package.json index 305f7d6..e7ec146 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", "@lavamoat/allow-scripts": "^5.1.0", + "@lavamoat/harden": "^0.4.0", "@lavamoat/preinstall-always-fail": "^2.0.0", "@metamask/auto-changelog": "^6.1.0", "@metamask/eslint-config": "^15.0.0", @@ -84,6 +85,13 @@ "resolutions": { "fflate": "0.8.2" }, + "devEngines": { + "packageManager": { + "name": "yarn", + "version": ">=4.16.0+sha256.ba05224324578801b9cc98170d64aa50b9a36733b440fb0942306da3fbbdc7d1", + "onFail": "error" + } + }, "engines": { "node": "^22 || ^24 || >=26" }, @@ -93,5 +101,8 @@ "@lavamoat/preinstall-always-fail": false, "eslint-plugin-import-x>unrs-resolver": false } + }, + "scriptsConfig": { + "#default": "lavamoat/scripts.loose.json" } } diff --git a/yarn.lock b/yarn.lock index a403e4f..a673088 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,6 +19,15 @@ __metadata: languageName: node linkType: hard +"@arcanis/slice-ansi@npm:^1.1.1": + version: 1.1.1 + resolution: "@arcanis/slice-ansi@npm:1.1.1" + dependencies: + grapheme-splitter: "npm:^1.0.4" + checksum: 10/14ed60cb45750d386c64229ac7bab20e10eedc193503fa4decff764162d329d6d3363ed2cd3debec833186ee54affe4f824f6e8eff531295117fd1ebda200270 + languageName: node + linkType: hard + "@arethetypeswrong/cli@npm:^0.15.3": version: 0.15.3 resolution: "@arethetypeswrong/cli@npm:0.15.3" @@ -512,6 +521,21 @@ __metadata: languageName: node linkType: hard +"@lavamoat/harden@npm:^0.4.0": + version: 0.4.0 + resolution: "@lavamoat/harden@npm:0.4.0" + dependencies: + "@yarnpkg/core": "npm:4.8.0" + "@yarnpkg/fslib": "npm:3.1.5" + consola: "npm:3.4.2" + semver: "npm:^7.7.2" + yaml: "npm:^2.7.1" + bin: + harden: src/cli.js + checksum: 10/6966c8ccd15b9c1615a99b6ada5aeb799fe1c50fc3d64c4c261ab307067db45210e3465cfa19532b0516fa87074eac48be3fdfae8e4bf30f242238fa4cb6fa3c + languageName: node + linkType: hard + "@lavamoat/preinstall-always-fail@npm:^2.0.0": version: 2.0.0 resolution: "@lavamoat/preinstall-always-fail@npm:2.0.0" @@ -611,6 +635,7 @@ __metadata: dependencies: "@arethetypeswrong/cli": "npm:^0.15.3" "@lavamoat/allow-scripts": "npm:^5.1.0" + "@lavamoat/harden": "npm:^0.4.0" "@lavamoat/preinstall-always-fail": "npm:^2.0.0" "@metamask/auto-changelog": "npm:^6.1.0" "@metamask/eslint-config": "npm:^15.0.0" @@ -1219,7 +1244,7 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/is@npm:^4.6.0": +"@sindresorhus/is@npm:^4.0.0, @sindresorhus/is@npm:^4.6.0": version: 4.6.0 resolution: "@sindresorhus/is@npm:4.6.0" checksum: 10/e7f36ed72abfcd5e0355f7423a72918b9748bb1ef370a59f3e5ad8d40b728b85d63b272f65f63eec1faf417cda89dcb0aeebe94015647b6054659c1442fe5ce0 @@ -1233,6 +1258,15 @@ __metadata: languageName: node linkType: hard +"@szmarczak/http-timer@npm:^4.0.5": + version: 4.0.6 + resolution: "@szmarczak/http-timer@npm:4.0.6" + dependencies: + defer-to-connect: "npm:^2.0.0" + checksum: 10/c29df3bcec6fc3bdec2b17981d89d9c9fc9bd7d0c9bcfe92821dc533f4440bc890ccde79971838b4ceed1921d456973c4180d7175ee1d0023ad0562240a58d95 + languageName: node + linkType: hard + "@tootallnate/once@npm:2": version: 2.0.1 resolution: "@tootallnate/once@npm:2.0.1" @@ -1310,6 +1344,18 @@ __metadata: languageName: node linkType: hard +"@types/cacheable-request@npm:^6.0.1": + version: 6.0.3 + resolution: "@types/cacheable-request@npm:6.0.3" + dependencies: + "@types/http-cache-semantics": "npm:*" + "@types/keyv": "npm:^3.1.4" + "@types/node": "npm:*" + "@types/responselike": "npm:^1.0.0" + checksum: 10/159f9fdb2a1b7175eef453ae2ced5ea04c0d2b9610cc9ccd9f9abb066d36dacb1f37acd879ace10ad7cbb649490723feb396fb7307004c9670be29636304b988 + languageName: node + linkType: hard + "@types/chai@npm:^5.2.2": version: 5.2.3 resolution: "@types/chai@npm:5.2.3" @@ -1334,6 +1380,13 @@ __metadata: languageName: node linkType: hard +"@types/emscripten@npm:^1.39.6": + version: 1.41.5 + resolution: "@types/emscripten@npm:1.41.5" + checksum: 10/60dfcced39b2d0c94f31907c5cf5d97fe06ed35ed6cb134650a1a96bae861302722d4a6f459b484ea09588cde70cbcc034974454a746be3ce9688b52398d2953 + languageName: node + linkType: hard + "@types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" @@ -1350,6 +1403,13 @@ __metadata: languageName: node linkType: hard +"@types/http-cache-semantics@npm:*": + version: 4.2.0 + resolution: "@types/http-cache-semantics@npm:4.2.0" + checksum: 10/01ea0dc9c1852267f5f9a0190846ac158707994b8e325bca190385ec97aa773d4a99cd333e22e838bde3c9aba59e2b5a6ac399b494c203587c6d8f28d21d6326 + languageName: node + linkType: hard + "@types/json-schema@npm:^7.0.15": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -1357,6 +1417,15 @@ __metadata: languageName: node linkType: hard +"@types/keyv@npm:^3.1.4": + version: 3.1.4 + resolution: "@types/keyv@npm:3.1.4" + dependencies: + "@types/node": "npm:*" + checksum: 10/e009a2bfb50e90ca9b7c6e8f648f8464067271fd99116f881073fa6fa76dc8d0133181dd65e6614d5fb1220d671d67b0124aef7d97dc02d7e342ab143a47779d + languageName: node + linkType: hard + "@types/mdast@npm:^4.0.0": version: 4.0.4 resolution: "@types/mdast@npm:4.0.4" @@ -1373,6 +1442,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:*": + version: 26.1.1 + resolution: "@types/node@npm:26.1.1" + dependencies: + undici-types: "npm:~8.3.0" + checksum: 10/df6555a94c6b4cf74e6238373e2881e72dc91058cf2ba173be77ea3974aaa8f459c2f10fbb7eb644fb1e5189dd8407097f5d39506fad39c89bde18acb3b90316 + languageName: node + linkType: hard + "@types/node@npm:^18.18": version: 18.19.34 resolution: "@types/node@npm:18.19.34" @@ -1389,6 +1467,29 @@ __metadata: languageName: node linkType: hard +"@types/responselike@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/responselike@npm:1.0.3" + dependencies: + "@types/node": "npm:*" + checksum: 10/6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 + languageName: node + linkType: hard + +"@types/semver@npm:^7.1.0": + version: 7.7.1 + resolution: "@types/semver@npm:7.7.1" + checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068 + languageName: node + linkType: hard + +"@types/treeify@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/treeify@npm:1.0.3" + checksum: 10/777e579b30a916a781e7cbad2b7a76bc5473ff7bfe7167dd6de47f80f4386df5bf3d0dc34170afb75d52e75f6ed61cc109abf2324e093c1f9ecd4e79fec58d0c + languageName: node + linkType: hard + "@types/unist@npm:*, @types/unist@npm:^3.0.0": version: 3.0.3 resolution: "@types/unist@npm:3.0.3" @@ -1836,6 +1937,90 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/core@npm:4.8.0": + version: 4.8.0 + resolution: "@yarnpkg/core@npm:4.8.0" + dependencies: + "@arcanis/slice-ansi": "npm:^1.1.1" + "@types/semver": "npm:^7.1.0" + "@types/treeify": "npm:^1.0.0" + "@yarnpkg/fslib": "npm:^3.1.5" + "@yarnpkg/libzip": "npm:^3.2.2" + "@yarnpkg/parsers": "npm:^3.0.3" + "@yarnpkg/shell": "npm:^4.1.3" + camelcase: "npm:^5.3.1" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.0.0" + clipanion: "npm:^4.0.0-rc.2" + cross-spawn: "npm:^7.0.3" + diff: "npm:^5.1.0" + dotenv: "npm:^16.3.1" + es-toolkit: "npm:^1.39.7" + fast-glob: "npm:^3.2.2" + got: "npm:^11.7.0" + hpagent: "npm:^1.2.0" + micromatch: "npm:^4.0.2" + p-limit: "npm:^2.2.0" + semver: "npm:^7.1.2" + strip-ansi: "npm:^6.0.0" + tar: "npm:^7.5.3" + tinylogic: "npm:^2.0.0" + treeify: "npm:^1.1.0" + tslib: "npm:^2.4.0" + checksum: 10/ae9986ac1e680f78ba80539b7e690ac6458dcf582bed334e7e302f54710adba5e82e794d2c413800ff9c245910c40612c5bb6e888952975bd2e6778f18f63b73 + languageName: node + linkType: hard + +"@yarnpkg/fslib@npm:3.1.5, @yarnpkg/fslib@npm:^3.1.2, @yarnpkg/fslib@npm:^3.1.3, @yarnpkg/fslib@npm:^3.1.5": + version: 3.1.5 + resolution: "@yarnpkg/fslib@npm:3.1.5" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/67b4850cdfbf0c11460302d997c0eacab46246cc8c7718a045beca346c494163e15768e2d20ab719ff6a98adbe7eaa9efcecdfd5cb0b8539f84a96449ac7ceaa + languageName: node + linkType: hard + +"@yarnpkg/libzip@npm:^3.2.2": + version: 3.2.2 + resolution: "@yarnpkg/libzip@npm:3.2.2" + dependencies: + "@types/emscripten": "npm:^1.39.6" + "@yarnpkg/fslib": "npm:^3.1.3" + tslib: "npm:^2.4.0" + peerDependencies: + "@yarnpkg/fslib": ^3.1.3 + checksum: 10/b6548be0a421e2390b74fd767d5f90e6da34a84af3ca28389b86d7f9e7602663f01347b5081cb93f8821877cae3ed48d2cb1cb8c35a4a4f7fc3d00109c85af0f + languageName: node + linkType: hard + +"@yarnpkg/parsers@npm:^3.0.3": + version: 3.0.3 + resolution: "@yarnpkg/parsers@npm:3.0.3" + dependencies: + js-yaml: "npm:^3.10.0" + tslib: "npm:^2.4.0" + checksum: 10/379f7ff8fc1b37d3818dfeba4e18a72f8e9817bb41aab9332b50bbc843e45c9bf135563a7a06882ffb50e4cdd29c8da33c8e4f3739201de2fbcd38ecb59e3a8e + languageName: node + linkType: hard + +"@yarnpkg/shell@npm:^4.1.3": + version: 4.1.3 + resolution: "@yarnpkg/shell@npm:4.1.3" + dependencies: + "@yarnpkg/fslib": "npm:^3.1.2" + "@yarnpkg/parsers": "npm:^3.0.3" + chalk: "npm:^4.1.2" + clipanion: "npm:^4.0.0-rc.2" + cross-spawn: "npm:^7.0.3" + fast-glob: "npm:^3.2.2" + micromatch: "npm:^4.0.2" + tslib: "npm:^2.4.0" + bin: + shell: ./lib/cli.js + checksum: 10/5994f92adf960071ac938653c5ad09746285d3fdc452fc6fdd30c3a832b612cc208e8d2274731e35957b457b168d6be524f5ce30ceb18542532d9326b422421b + languageName: node + linkType: hard + "@yarnpkg/types@npm:^4.0.0-rc.52": version: 4.0.0-rc.52 resolution: "@yarnpkg/types@npm:4.0.0-rc.52" @@ -2151,6 +2336,28 @@ __metadata: languageName: node linkType: hard +"cacheable-lookup@npm:^5.0.3": + version: 5.0.4 + resolution: "cacheable-lookup@npm:5.0.4" + checksum: 10/618a8b3eea314060e74cb3285a6154e8343c244a34235acf91cfe626ee0705c24e3cd11e4b1a7b3900bd749ee203ae65afe13adf610c8ab173e99d4a208faf75 + languageName: node + linkType: hard + +"cacheable-request@npm:^7.0.2": + version: 7.0.4 + resolution: "cacheable-request@npm:7.0.4" + dependencies: + clone-response: "npm:^1.0.2" + get-stream: "npm:^5.1.0" + http-cache-semantics: "npm:^4.0.0" + keyv: "npm:^4.0.0" + lowercase-keys: "npm:^2.0.0" + normalize-url: "npm:^6.0.1" + responselike: "npm:^2.0.0" + checksum: 10/0f4f2001260ecca78b9f64fc8245e6b5a5dcde24ea53006daab71f5e0e1338095aa1512ec099c4f9895a9e5acfac9da423cb7c079e131485891e9214aca46c41 + languageName: node + linkType: hard + "callsite@npm:^1.0.0": version: 1.0.0 resolution: "callsite@npm:1.0.0" @@ -2165,6 +2372,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: 10/e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b + languageName: node + linkType: hard + "camelcase@npm:^6.3.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" @@ -2257,6 +2471,13 @@ __metadata: languageName: node linkType: hard +"ci-info@npm:^4.0.0": + version: 4.4.0 + resolution: "ci-info@npm:4.4.0" + checksum: 10/dfded0c630267d89660c8abb988ac8395a382bdfefedcc03e3e2858523312c5207db777c239c34774e3fcff11f015477c19d2ac8a58ea58aa476614a2e64f434 + languageName: node + linkType: hard + "cjs-module-lexer@npm:^1.3.1": version: 1.4.1 resolution: "cjs-module-lexer@npm:1.4.1" @@ -2284,6 +2505,17 @@ __metadata: languageName: node linkType: hard +"clipanion@npm:^4.0.0-rc.2": + version: 4.0.0-rc.4 + resolution: "clipanion@npm:4.0.0-rc.4" + dependencies: + typanion: "npm:^3.8.0" + peerDependencies: + typanion: "*" + checksum: 10/c3a94783318d91e6b35380a8aa4a6f166964082a51ff2df21a339266223aaab98f5986dd2c37ca7fd640ad1d233b3cd5b24aad64c51537b54ccc9c66ec070eeb + languageName: node + linkType: hard + "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -2306,6 +2538,15 @@ __metadata: languageName: node linkType: hard +"clone-response@npm:^1.0.2": + version: 1.0.3 + resolution: "clone-response@npm:1.0.3" + dependencies: + mimic-response: "npm:^1.0.0" + checksum: 10/4e671cac39b11c60aa8ba0a450657194a5d6504df51bca3fac5b3bd0145c4f8e8464898f87c8406b83232e3bc5cca555f51c1f9c8ac023969ebfbf7f6bdabb2e + languageName: node + linkType: hard + "cmd-shim@npm:^6.0.0": version: 6.0.1 resolution: "cmd-shim@npm:6.0.1" @@ -2366,6 +2607,13 @@ __metadata: languageName: node linkType: hard +"consola@npm:3.4.2": + version: 3.4.2 + resolution: "consola@npm:3.4.2" + checksum: 10/32192c9f50d7cac27c5d7c4ecd3ff3679aea863e6bf5bd6a9cc2b05d1cd78addf5dae71df08c54330c142be8e7fbd46f051030129b57c6aacdd771efe409c4b2 + languageName: node + linkType: hard + "console-control-strings@npm:^1.1.0": version: 1.1.0 resolution: "console-control-strings@npm:1.1.0" @@ -2432,6 +2680,15 @@ __metadata: languageName: node linkType: hard +"decompress-response@npm:^6.0.0": + version: 6.0.0 + resolution: "decompress-response@npm:6.0.0" + dependencies: + mimic-response: "npm:^3.1.0" + checksum: 10/d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 + languageName: node + linkType: hard + "deep-is@npm:^0.1.3": version: 0.1.3 resolution: "deep-is@npm:0.1.3" @@ -2439,6 +2696,13 @@ __metadata: languageName: node linkType: hard +"defer-to-connect@npm:^2.0.0": + version: 2.0.1 + resolution: "defer-to-connect@npm:2.0.1" + checksum: 10/8a9b50d2f25446c0bfefb55a48e90afd58f85b21bcf78e9207cd7b804354f6409032a1705c2491686e202e64fc05f147aa5aa45f9aa82627563f045937f5791b + languageName: node + linkType: hard + "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -2537,10 +2801,17 @@ __metadata: languageName: node linkType: hard -"diff@npm:^5.0.0": - version: 5.0.0 - resolution: "diff@npm:5.0.0" - checksum: 10/4a179a75b17cbb420eb9145be913f9ddb34b47cb2ba4301e80ae745122826a468f02ca8f5e56945958de26ace594899c8381acb6659c88e7803ef078b53d690c +"diff@npm:^5.0.0, diff@npm:^5.1.0": + version: 5.2.2 + resolution: "diff@npm:5.2.2" + checksum: 10/8a885b38113d96138d87f6cb474ee959b7e9ab33c0c4cb1b07dcf019ec544945a2309d53d721532af020de4b3a58fb89f1026f64f42f9421aa9c3ae48a36998b + languageName: node + linkType: hard + +"dotenv@npm:^16.3.1": + version: 16.6.1 + resolution: "dotenv@npm:16.6.1" + checksum: 10/1d1897144344447ffe62aa1a6d664f4cd2e0784e0aff787eeeec1940ded32f8e4b5b506d665134fc87157baa086fce07ec6383970a2b6d2e7985beaed6a4cc14 languageName: node linkType: hard @@ -2574,6 +2845,15 @@ __metadata: languageName: node linkType: hard +"end-of-stream@npm:^1.1.0": + version: 1.4.5 + resolution: "end-of-stream@npm:1.4.5" + dependencies: + once: "npm:^1.4.0" + checksum: 10/1e0cfa6e7f49887544e03314f9dfc56a8cb6dde910cbb445983ecc2ff426fc05946df9d75d8a21a3a64f2cecfe1bf88f773952029f46756b2ed64a24e95b1fb8 + languageName: node + linkType: hard + "enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": version: 5.17.1 resolution: "enhanced-resolve@npm:5.17.1" @@ -2642,6 +2922,20 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.39.7": + version: 1.49.0 + resolution: "es-toolkit@npm:1.49.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + vitepress-plugin-sandpack@1.1.4: + unplugged: true + checksum: 10/ff0377f1fa681e6b58c06ec46cd3683c02df499f5101effb70bfbf4d69fce2e6a13889b182f68c495e25cdee31829f21dfd6094f722d4de82c546c2a32d0c670 + languageName: node + linkType: hard + "escalade@npm:^3.1.1, escalade@npm:^3.2.0": version: 3.2.0 resolution: "escalade@npm:3.2.0" @@ -3034,16 +3328,16 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.3.2": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" +"fast-glob@npm:^3.2.2, fast-glob@npm:^3.3.2": + version: 3.3.3 + resolution: "fast-glob@npm:3.3.3" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df + micromatch: "npm:^4.0.8" + checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad languageName: node linkType: hard @@ -3218,6 +3512,15 @@ __metadata: languageName: node linkType: hard +"get-stream@npm:^5.1.0": + version: 5.2.0 + resolution: "get-stream@npm:5.2.0" + dependencies: + pump: "npm:^3.0.0" + checksum: 10/13a73148dca795e41421013da6e3ebff8ccb7fba4d2f023fd0c6da2c166ec4e789bec9774a73a7b49c08daf2cae552f8a3e914042ac23b5f59dd278cc8f9cbfb + languageName: node + linkType: hard + "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -3328,6 +3631,25 @@ __metadata: languageName: node linkType: hard +"got@npm:^11.7.0": + version: 11.8.6 + resolution: "got@npm:11.8.6" + dependencies: + "@sindresorhus/is": "npm:^4.0.0" + "@szmarczak/http-timer": "npm:^4.0.5" + "@types/cacheable-request": "npm:^6.0.1" + "@types/responselike": "npm:^1.0.0" + cacheable-lookup: "npm:^5.0.3" + cacheable-request: "npm:^7.0.2" + decompress-response: "npm:^6.0.0" + http2-wrapper: "npm:^1.0.0-beta.5.2" + lowercase-keys: "npm:^2.0.0" + p-cancelable: "npm:^2.0.0" + responselike: "npm:^2.0.0" + checksum: 10/a30c74029d81bd5fe50dea1a0c970595d792c568e188ff8be254b5bc11e6158d1b014570772d4a30d0a97723e7dd34e7c8cc1a2f23018f60aece3070a7a5c2a5 + languageName: node + linkType: hard + "graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" @@ -3335,6 +3657,13 @@ __metadata: languageName: node linkType: hard +"grapheme-splitter@npm:^1.0.4": + version: 1.0.4 + resolution: "grapheme-splitter@npm:1.0.4" + checksum: 10/fdb2f51fd430ce881e18e44c4934ad30e59736e46213f7ad35ea5970a9ebdf7d0fe56150d15cc98230d55d2fd48c73dc6781494c38d8cf2405718366c36adb88 + languageName: node + linkType: hard + "graphemer@npm:^1.4.0": version: 1.4.0 resolution: "graphemer@npm:1.4.0" @@ -3411,6 +3740,13 @@ __metadata: languageName: node linkType: hard +"hpagent@npm:^1.2.0": + version: 1.2.0 + resolution: "hpagent@npm:1.2.0" + checksum: 10/bad186449da7e3456788a8cbae459fc6c0a855d5872a7f460c48ce4a613020d8d914839dad10047297099299c4f9e6c65a0eec3f5886af196c0a516e4ad8a845 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -3425,10 +3761,10 @@ __metadata: languageName: node linkType: hard -"http-cache-semantics@npm:^4.1.0": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f +"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 languageName: node linkType: hard @@ -3443,6 +3779,16 @@ __metadata: languageName: node linkType: hard +"http2-wrapper@npm:^1.0.0-beta.5.2": + version: 1.0.3 + resolution: "http2-wrapper@npm:1.0.3" + dependencies: + quick-lru: "npm:^5.1.1" + resolve-alpn: "npm:^1.0.0" + checksum: 10/8097ee2699440c2e64bda52124990cc5b0fb347401c7797b1a0c1efd5a0f79a4ebaa68e8a6ac3e2dde5f09460c1602764da6da2412bad628ed0a3b0ae35e72d4 + languageName: node + linkType: hard + "https-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "https-proxy-agent@npm:5.0.0" @@ -3689,7 +4035,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.14.1": +"js-yaml@npm:^3.10.0, js-yaml@npm:^3.14.1": version: 3.15.1 resolution: "js-yaml@npm:3.15.1" dependencies: @@ -3779,7 +4125,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.5.4": +"keyv@npm:^4.0.0, keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -3957,6 +4303,13 @@ __metadata: languageName: node linkType: hard +"lowercase-keys@npm:^2.0.0": + version: 2.0.0 + resolution: "lowercase-keys@npm:2.0.0" + checksum: 10/1c233d2da35056e8c49fae8097ee061b8c799b2f02e33c2bf32f9913c7de8fb481ab04dab7df35e94156c800f5f34e99acbf32b21781d87c3aa43ef7b748b79e + languageName: node + linkType: hard + "lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": version: 11.5.2 resolution: "lru-cache@npm:11.5.2" @@ -4168,7 +4521,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.4": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -4185,6 +4538,20 @@ __metadata: languageName: node linkType: hard +"mimic-response@npm:^1.0.0": + version: 1.0.1 + resolution: "mimic-response@npm:1.0.1" + checksum: 10/034c78753b0e622bc03c983663b1cdf66d03861050e0c8606563d149bc2b02d63f62ce4d32be4ab50d0553ae0ffe647fc34d1f5281184c6e1e8cf4d85e8d9823 + languageName: node + linkType: hard + +"mimic-response@npm:^3.1.0": + version: 3.1.0 + resolution: "mimic-response@npm:3.1.0" + checksum: 10/7e719047612411fe071332a7498cf0448bbe43c485c0d780046c76633a771b223ff49bd00267be122cedebb897037fdb527df72335d0d0f74724604ca70b37ad + languageName: node + linkType: hard + "minimatch@npm:^10.2.2, minimatch@npm:^9.0.3 || ^10.0.1": version: 10.2.6 resolution: "minimatch@npm:10.2.6" @@ -4465,6 +4832,13 @@ __metadata: languageName: node linkType: hard +"normalize-url@npm:^6.0.1": + version: 6.1.0 + resolution: "normalize-url@npm:6.1.0" + checksum: 10/5ae699402c9d5ffa330adc348fcd6fc6e6a155ab7c811b96e30b7ecab60ceef821d8f86443869671dda71bbc47f4b9625739c82ad247e883e9aefe875bfb8659 + languageName: node + linkType: hard + "npm-install-checks@npm:^8.0.0": version: 8.0.0 resolution: "npm-install-checks@npm:8.0.0" @@ -4540,7 +4914,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.4.0": +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -4650,6 +5024,22 @@ __metadata: languageName: node linkType: hard +"p-cancelable@npm:^2.0.0": + version: 2.1.1 + resolution: "p-cancelable@npm:2.1.1" + checksum: 10/7f1b64db17fc54acf359167d62898115dcf2a64bf6b3b038e4faf36fc059e5ed762fb9624df8ed04b25bee8de3ab8d72dea9879a2a960cd12e23c420a4aca6ed + languageName: node + linkType: hard + +"p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: "npm:^2.0.0" + checksum: 10/84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 + languageName: node + linkType: hard + "p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" @@ -4677,6 +5067,13 @@ __metadata: languageName: node linkType: hard +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: 10/f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -4855,6 +5252,16 @@ __metadata: languageName: node linkType: hard +"pump@npm:^3.0.0": + version: 3.0.4 + resolution: "pump@npm:3.0.4" + dependencies: + end-of-stream: "npm:^1.1.0" + once: "npm:^1.3.1" + checksum: 10/d043c3e710c56ffd280711e98a94e863ab334f79ea43cee0fb70e1349b2355ffd2ff287c7522e4c960a247699d5b7825f00fa090b85d6179c973be13f78a6c49 + languageName: node + linkType: hard + "punycode.js@npm:^2.3.1": version: 2.3.1 resolution: "punycode.js@npm:2.3.1" @@ -4876,6 +5283,13 @@ __metadata: languageName: node linkType: hard +"quick-lru@npm:^5.1.1": + version: 5.1.1 + resolution: "quick-lru@npm:5.1.1" + checksum: 10/a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed + languageName: node + linkType: hard + "read-cmd-shim@npm:^4.0.0": version: 4.0.0 resolution: "read-cmd-shim@npm:4.0.0" @@ -4933,6 +5347,13 @@ __metadata: languageName: node linkType: hard +"resolve-alpn@npm:^1.0.0": + version: 1.2.1 + resolution: "resolve-alpn@npm:1.2.1" + checksum: 10/744e87888f0b6fa0b256ab454ca0b9c0b80808715e2ef1f3672773665c92a941f6181194e30ccae4a8cd0adbe0d955d3f133102636d2ee0cca0119fec0bc9aec + languageName: node + linkType: hard + "resolve-dir@npm:^1.0.0, resolve-dir@npm:^1.0.1": version: 1.0.1 resolution: "resolve-dir@npm:1.0.1" @@ -4992,6 +5413,15 @@ __metadata: languageName: node linkType: hard +"responselike@npm:^2.0.0": + version: 2.0.1 + resolution: "responselike@npm:2.0.1" + dependencies: + lowercase-keys: "npm:^2.0.0" + checksum: 10/b122535466e9c97b55e69c7f18e2be0ce3823c5d47ee8de0d9c0b114aa55741c6db8bfbfce3766a94d1272e61bfb1ebf0a15e9310ac5629fbb7446a861b4fd3a + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -5114,12 +5544,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.2": - version: 7.7.2 - resolution: "semver@npm:7.7.2" +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.2": + version: 7.8.5 + resolution: "semver@npm:7.8.5" bin: semver: bin/semver.js - checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda + checksum: 10/9b01d2ff11e6e4a4539b7ca3c5f280c8704cb397a28504469f2ed4f00ad2194748d756647362a9712fff30984d15772ab7f083108c2fb508e2096ae9e708f22c languageName: node linkType: hard @@ -5417,7 +5847,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^7.5.4": +"tar@npm:^7.5.3, tar@npm:^7.5.4": version: 7.5.22 resolution: "tar@npm:7.5.22" dependencies: @@ -5461,6 +5891,13 @@ __metadata: languageName: node linkType: hard +"tinylogic@npm:^2.0.0": + version: 2.0.0 + resolution: "tinylogic@npm:2.0.0" + checksum: 10/6467b1ed9b602dae035726ee3faf2682bddffb5389b42fdb4daf13878037420ed9981a572ca7db467bd26c4ab00fb4eefe654f24e35984ec017fb5e83081db97 + languageName: node + linkType: hard + "tinypool@npm:2.1.0": version: 2.1.0 resolution: "tinypool@npm:2.1.0" @@ -5484,6 +5921,13 @@ __metadata: languageName: node linkType: hard +"treeify@npm:^1.1.0": + version: 1.1.0 + resolution: "treeify@npm:1.1.0" + checksum: 10/5241976a751168fb9894a12d031299f1f6337b7f2cbd3eff22ee86e6777620352a69a1cab0d4709251317ff307eeda0dc45918850974fc44f4c7fc50e623b990 + languageName: node + linkType: hard + "trim-lines@npm:^3.0.0": version: 3.0.1 resolution: "trim-lines@npm:3.0.1" @@ -5552,6 +5996,13 @@ __metadata: languageName: node linkType: hard +"typanion@npm:^3.8.0": + version: 3.14.0 + resolution: "typanion@npm:3.14.0" + checksum: 10/5e88d9e6121ff0ec543f572152fdd1b70e9cca35406d79013ec8e08defa8ef96de5fec9e98da3afbd1eb4426b9e8e8fe423163d0b482e34a40103cab1ef29abd + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -5654,6 +6105,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~8.3.0": + version: 8.3.0 + resolution: "undici-types@npm:8.3.0" + checksum: 10/6681d2837ac75a75ac1cc46090aa2b8ddc7c6b8ecc295a6cdb06838752a730da3d8afeecf05e5ab7903160eafad3a8b6ffa1927e5ded260590f4d4fef18646d5 + languageName: node + linkType: hard + "undici@npm:^6.25.0": version: 6.28.0 resolution: "undici@npm:6.28.0" @@ -6117,12 +6575,12 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.5.1": - version: 2.6.0 - resolution: "yaml@npm:2.6.0" +"yaml@npm:^2.5.1, yaml@npm:^2.7.1": + version: 2.9.0 + resolution: "yaml@npm:2.9.0" bin: yaml: bin.mjs - checksum: 10/f4369f667c7626c216ea81b5840fe9b530cdae4cff2d84d166ec1239e54bf332dbfac4a71bf60d121f8e85e175364a4e280a520292269b6cf9d074368309adf9 + checksum: 10/9a95e8e08651c3d292ab6a5befeb5f57b76801caa097c75bb45c9a70ce19c1b11f57e87a6ef84a579ea070ed2c2c8ac541c88c0ae684d544d5f42c7e77d11b7b languageName: node linkType: hard From 33790c1cfbe5c8966e3dd6a9c7b7665a6d3a77de Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Thu, 16 Jul 2026 10:12:32 +0200 Subject: [PATCH 02/19] Remove `@lavamoat/harden` dependency --- package.json | 1 - yarn.lock | 506 +++------------------------------------------------ 2 files changed, 24 insertions(+), 483 deletions(-) diff --git a/package.json b/package.json index e7ec146..3d4c2dd 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", "@lavamoat/allow-scripts": "^5.1.0", - "@lavamoat/harden": "^0.4.0", "@lavamoat/preinstall-always-fail": "^2.0.0", "@metamask/auto-changelog": "^6.1.0", "@metamask/eslint-config": "^15.0.0", diff --git a/yarn.lock b/yarn.lock index a673088..fc1d771 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,15 +19,6 @@ __metadata: languageName: node linkType: hard -"@arcanis/slice-ansi@npm:^1.1.1": - version: 1.1.1 - resolution: "@arcanis/slice-ansi@npm:1.1.1" - dependencies: - grapheme-splitter: "npm:^1.0.4" - checksum: 10/14ed60cb45750d386c64229ac7bab20e10eedc193503fa4decff764162d329d6d3363ed2cd3debec833186ee54affe4f824f6e8eff531295117fd1ebda200270 - languageName: node - linkType: hard - "@arethetypeswrong/cli@npm:^0.15.3": version: 0.15.3 resolution: "@arethetypeswrong/cli@npm:0.15.3" @@ -521,21 +512,6 @@ __metadata: languageName: node linkType: hard -"@lavamoat/harden@npm:^0.4.0": - version: 0.4.0 - resolution: "@lavamoat/harden@npm:0.4.0" - dependencies: - "@yarnpkg/core": "npm:4.8.0" - "@yarnpkg/fslib": "npm:3.1.5" - consola: "npm:3.4.2" - semver: "npm:^7.7.2" - yaml: "npm:^2.7.1" - bin: - harden: src/cli.js - checksum: 10/6966c8ccd15b9c1615a99b6ada5aeb799fe1c50fc3d64c4c261ab307067db45210e3465cfa19532b0516fa87074eac48be3fdfae8e4bf30f242238fa4cb6fa3c - languageName: node - linkType: hard - "@lavamoat/preinstall-always-fail@npm:^2.0.0": version: 2.0.0 resolution: "@lavamoat/preinstall-always-fail@npm:2.0.0" @@ -635,7 +611,6 @@ __metadata: dependencies: "@arethetypeswrong/cli": "npm:^0.15.3" "@lavamoat/allow-scripts": "npm:^5.1.0" - "@lavamoat/harden": "npm:^0.4.0" "@lavamoat/preinstall-always-fail": "npm:^2.0.0" "@metamask/auto-changelog": "npm:^6.1.0" "@metamask/eslint-config": "npm:^15.0.0" @@ -1244,7 +1219,7 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/is@npm:^4.0.0, @sindresorhus/is@npm:^4.6.0": +"@sindresorhus/is@npm:^4.6.0": version: 4.6.0 resolution: "@sindresorhus/is@npm:4.6.0" checksum: 10/e7f36ed72abfcd5e0355f7423a72918b9748bb1ef370a59f3e5ad8d40b728b85d63b272f65f63eec1faf417cda89dcb0aeebe94015647b6054659c1442fe5ce0 @@ -1258,15 +1233,6 @@ __metadata: languageName: node linkType: hard -"@szmarczak/http-timer@npm:^4.0.5": - version: 4.0.6 - resolution: "@szmarczak/http-timer@npm:4.0.6" - dependencies: - defer-to-connect: "npm:^2.0.0" - checksum: 10/c29df3bcec6fc3bdec2b17981d89d9c9fc9bd7d0c9bcfe92821dc533f4440bc890ccde79971838b4ceed1921d456973c4180d7175ee1d0023ad0562240a58d95 - languageName: node - linkType: hard - "@tootallnate/once@npm:2": version: 2.0.1 resolution: "@tootallnate/once@npm:2.0.1" @@ -1344,18 +1310,6 @@ __metadata: languageName: node linkType: hard -"@types/cacheable-request@npm:^6.0.1": - version: 6.0.3 - resolution: "@types/cacheable-request@npm:6.0.3" - dependencies: - "@types/http-cache-semantics": "npm:*" - "@types/keyv": "npm:^3.1.4" - "@types/node": "npm:*" - "@types/responselike": "npm:^1.0.0" - checksum: 10/159f9fdb2a1b7175eef453ae2ced5ea04c0d2b9610cc9ccd9f9abb066d36dacb1f37acd879ace10ad7cbb649490723feb396fb7307004c9670be29636304b988 - languageName: node - linkType: hard - "@types/chai@npm:^5.2.2": version: 5.2.3 resolution: "@types/chai@npm:5.2.3" @@ -1380,13 +1334,6 @@ __metadata: languageName: node linkType: hard -"@types/emscripten@npm:^1.39.6": - version: 1.41.5 - resolution: "@types/emscripten@npm:1.41.5" - checksum: 10/60dfcced39b2d0c94f31907c5cf5d97fe06ed35ed6cb134650a1a96bae861302722d4a6f459b484ea09588cde70cbcc034974454a746be3ce9688b52398d2953 - languageName: node - linkType: hard - "@types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" @@ -1403,13 +1350,6 @@ __metadata: languageName: node linkType: hard -"@types/http-cache-semantics@npm:*": - version: 4.2.0 - resolution: "@types/http-cache-semantics@npm:4.2.0" - checksum: 10/01ea0dc9c1852267f5f9a0190846ac158707994b8e325bca190385ec97aa773d4a99cd333e22e838bde3c9aba59e2b5a6ac399b494c203587c6d8f28d21d6326 - languageName: node - linkType: hard - "@types/json-schema@npm:^7.0.15": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -1417,15 +1357,6 @@ __metadata: languageName: node linkType: hard -"@types/keyv@npm:^3.1.4": - version: 3.1.4 - resolution: "@types/keyv@npm:3.1.4" - dependencies: - "@types/node": "npm:*" - checksum: 10/e009a2bfb50e90ca9b7c6e8f648f8464067271fd99116f881073fa6fa76dc8d0133181dd65e6614d5fb1220d671d67b0124aef7d97dc02d7e342ab143a47779d - languageName: node - linkType: hard - "@types/mdast@npm:^4.0.0": version: 4.0.4 resolution: "@types/mdast@npm:4.0.4" @@ -1442,15 +1373,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": - version: 26.1.1 - resolution: "@types/node@npm:26.1.1" - dependencies: - undici-types: "npm:~8.3.0" - checksum: 10/df6555a94c6b4cf74e6238373e2881e72dc91058cf2ba173be77ea3974aaa8f459c2f10fbb7eb644fb1e5189dd8407097f5d39506fad39c89bde18acb3b90316 - languageName: node - linkType: hard - "@types/node@npm:^18.18": version: 18.19.34 resolution: "@types/node@npm:18.19.34" @@ -1467,29 +1389,6 @@ __metadata: languageName: node linkType: hard -"@types/responselike@npm:^1.0.0": - version: 1.0.3 - resolution: "@types/responselike@npm:1.0.3" - dependencies: - "@types/node": "npm:*" - checksum: 10/6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 - languageName: node - linkType: hard - -"@types/semver@npm:^7.1.0": - version: 7.7.1 - resolution: "@types/semver@npm:7.7.1" - checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068 - languageName: node - linkType: hard - -"@types/treeify@npm:^1.0.0": - version: 1.0.3 - resolution: "@types/treeify@npm:1.0.3" - checksum: 10/777e579b30a916a781e7cbad2b7a76bc5473ff7bfe7167dd6de47f80f4386df5bf3d0dc34170afb75d52e75f6ed61cc109abf2324e093c1f9ecd4e79fec58d0c - languageName: node - linkType: hard - "@types/unist@npm:*, @types/unist@npm:^3.0.0": version: 3.0.3 resolution: "@types/unist@npm:3.0.3" @@ -1937,90 +1836,6 @@ __metadata: languageName: node linkType: hard -"@yarnpkg/core@npm:4.8.0": - version: 4.8.0 - resolution: "@yarnpkg/core@npm:4.8.0" - dependencies: - "@arcanis/slice-ansi": "npm:^1.1.1" - "@types/semver": "npm:^7.1.0" - "@types/treeify": "npm:^1.0.0" - "@yarnpkg/fslib": "npm:^3.1.5" - "@yarnpkg/libzip": "npm:^3.2.2" - "@yarnpkg/parsers": "npm:^3.0.3" - "@yarnpkg/shell": "npm:^4.1.3" - camelcase: "npm:^5.3.1" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.0.0" - clipanion: "npm:^4.0.0-rc.2" - cross-spawn: "npm:^7.0.3" - diff: "npm:^5.1.0" - dotenv: "npm:^16.3.1" - es-toolkit: "npm:^1.39.7" - fast-glob: "npm:^3.2.2" - got: "npm:^11.7.0" - hpagent: "npm:^1.2.0" - micromatch: "npm:^4.0.2" - p-limit: "npm:^2.2.0" - semver: "npm:^7.1.2" - strip-ansi: "npm:^6.0.0" - tar: "npm:^7.5.3" - tinylogic: "npm:^2.0.0" - treeify: "npm:^1.1.0" - tslib: "npm:^2.4.0" - checksum: 10/ae9986ac1e680f78ba80539b7e690ac6458dcf582bed334e7e302f54710adba5e82e794d2c413800ff9c245910c40612c5bb6e888952975bd2e6778f18f63b73 - languageName: node - linkType: hard - -"@yarnpkg/fslib@npm:3.1.5, @yarnpkg/fslib@npm:^3.1.2, @yarnpkg/fslib@npm:^3.1.3, @yarnpkg/fslib@npm:^3.1.5": - version: 3.1.5 - resolution: "@yarnpkg/fslib@npm:3.1.5" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10/67b4850cdfbf0c11460302d997c0eacab46246cc8c7718a045beca346c494163e15768e2d20ab719ff6a98adbe7eaa9efcecdfd5cb0b8539f84a96449ac7ceaa - languageName: node - linkType: hard - -"@yarnpkg/libzip@npm:^3.2.2": - version: 3.2.2 - resolution: "@yarnpkg/libzip@npm:3.2.2" - dependencies: - "@types/emscripten": "npm:^1.39.6" - "@yarnpkg/fslib": "npm:^3.1.3" - tslib: "npm:^2.4.0" - peerDependencies: - "@yarnpkg/fslib": ^3.1.3 - checksum: 10/b6548be0a421e2390b74fd767d5f90e6da34a84af3ca28389b86d7f9e7602663f01347b5081cb93f8821877cae3ed48d2cb1cb8c35a4a4f7fc3d00109c85af0f - languageName: node - linkType: hard - -"@yarnpkg/parsers@npm:^3.0.3": - version: 3.0.3 - resolution: "@yarnpkg/parsers@npm:3.0.3" - dependencies: - js-yaml: "npm:^3.10.0" - tslib: "npm:^2.4.0" - checksum: 10/379f7ff8fc1b37d3818dfeba4e18a72f8e9817bb41aab9332b50bbc843e45c9bf135563a7a06882ffb50e4cdd29c8da33c8e4f3739201de2fbcd38ecb59e3a8e - languageName: node - linkType: hard - -"@yarnpkg/shell@npm:^4.1.3": - version: 4.1.3 - resolution: "@yarnpkg/shell@npm:4.1.3" - dependencies: - "@yarnpkg/fslib": "npm:^3.1.2" - "@yarnpkg/parsers": "npm:^3.0.3" - chalk: "npm:^4.1.2" - clipanion: "npm:^4.0.0-rc.2" - cross-spawn: "npm:^7.0.3" - fast-glob: "npm:^3.2.2" - micromatch: "npm:^4.0.2" - tslib: "npm:^2.4.0" - bin: - shell: ./lib/cli.js - checksum: 10/5994f92adf960071ac938653c5ad09746285d3fdc452fc6fdd30c3a832b612cc208e8d2274731e35957b457b168d6be524f5ce30ceb18542532d9326b422421b - languageName: node - linkType: hard - "@yarnpkg/types@npm:^4.0.0-rc.52": version: 4.0.0-rc.52 resolution: "@yarnpkg/types@npm:4.0.0-rc.52" @@ -2336,28 +2151,6 @@ __metadata: languageName: node linkType: hard -"cacheable-lookup@npm:^5.0.3": - version: 5.0.4 - resolution: "cacheable-lookup@npm:5.0.4" - checksum: 10/618a8b3eea314060e74cb3285a6154e8343c244a34235acf91cfe626ee0705c24e3cd11e4b1a7b3900bd749ee203ae65afe13adf610c8ab173e99d4a208faf75 - languageName: node - linkType: hard - -"cacheable-request@npm:^7.0.2": - version: 7.0.4 - resolution: "cacheable-request@npm:7.0.4" - dependencies: - clone-response: "npm:^1.0.2" - get-stream: "npm:^5.1.0" - http-cache-semantics: "npm:^4.0.0" - keyv: "npm:^4.0.0" - lowercase-keys: "npm:^2.0.0" - normalize-url: "npm:^6.0.1" - responselike: "npm:^2.0.0" - checksum: 10/0f4f2001260ecca78b9f64fc8245e6b5a5dcde24ea53006daab71f5e0e1338095aa1512ec099c4f9895a9e5acfac9da423cb7c079e131485891e9214aca46c41 - languageName: node - linkType: hard - "callsite@npm:^1.0.0": version: 1.0.0 resolution: "callsite@npm:1.0.0" @@ -2372,13 +2165,6 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.3.1": - version: 5.3.1 - resolution: "camelcase@npm:5.3.1" - checksum: 10/e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b - languageName: node - linkType: hard - "camelcase@npm:^6.3.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" @@ -2471,13 +2257,6 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.0.0": - version: 4.4.0 - resolution: "ci-info@npm:4.4.0" - checksum: 10/dfded0c630267d89660c8abb988ac8395a382bdfefedcc03e3e2858523312c5207db777c239c34774e3fcff11f015477c19d2ac8a58ea58aa476614a2e64f434 - languageName: node - linkType: hard - "cjs-module-lexer@npm:^1.3.1": version: 1.4.1 resolution: "cjs-module-lexer@npm:1.4.1" @@ -2505,17 +2284,6 @@ __metadata: languageName: node linkType: hard -"clipanion@npm:^4.0.0-rc.2": - version: 4.0.0-rc.4 - resolution: "clipanion@npm:4.0.0-rc.4" - dependencies: - typanion: "npm:^3.8.0" - peerDependencies: - typanion: "*" - checksum: 10/c3a94783318d91e6b35380a8aa4a6f166964082a51ff2df21a339266223aaab98f5986dd2c37ca7fd640ad1d233b3cd5b24aad64c51537b54ccc9c66ec070eeb - languageName: node - linkType: hard - "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -2538,15 +2306,6 @@ __metadata: languageName: node linkType: hard -"clone-response@npm:^1.0.2": - version: 1.0.3 - resolution: "clone-response@npm:1.0.3" - dependencies: - mimic-response: "npm:^1.0.0" - checksum: 10/4e671cac39b11c60aa8ba0a450657194a5d6504df51bca3fac5b3bd0145c4f8e8464898f87c8406b83232e3bc5cca555f51c1f9c8ac023969ebfbf7f6bdabb2e - languageName: node - linkType: hard - "cmd-shim@npm:^6.0.0": version: 6.0.1 resolution: "cmd-shim@npm:6.0.1" @@ -2607,13 +2366,6 @@ __metadata: languageName: node linkType: hard -"consola@npm:3.4.2": - version: 3.4.2 - resolution: "consola@npm:3.4.2" - checksum: 10/32192c9f50d7cac27c5d7c4ecd3ff3679aea863e6bf5bd6a9cc2b05d1cd78addf5dae71df08c54330c142be8e7fbd46f051030129b57c6aacdd771efe409c4b2 - languageName: node - linkType: hard - "console-control-strings@npm:^1.1.0": version: 1.1.0 resolution: "console-control-strings@npm:1.1.0" @@ -2680,15 +2432,6 @@ __metadata: languageName: node linkType: hard -"decompress-response@npm:^6.0.0": - version: 6.0.0 - resolution: "decompress-response@npm:6.0.0" - dependencies: - mimic-response: "npm:^3.1.0" - checksum: 10/d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 - languageName: node - linkType: hard - "deep-is@npm:^0.1.3": version: 0.1.3 resolution: "deep-is@npm:0.1.3" @@ -2696,13 +2439,6 @@ __metadata: languageName: node linkType: hard -"defer-to-connect@npm:^2.0.0": - version: 2.0.1 - resolution: "defer-to-connect@npm:2.0.1" - checksum: 10/8a9b50d2f25446c0bfefb55a48e90afd58f85b21bcf78e9207cd7b804354f6409032a1705c2491686e202e64fc05f147aa5aa45f9aa82627563f045937f5791b - languageName: node - linkType: hard - "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -2801,20 +2537,13 @@ __metadata: languageName: node linkType: hard -"diff@npm:^5.0.0, diff@npm:^5.1.0": +"diff@npm:^5.0.0": version: 5.2.2 resolution: "diff@npm:5.2.2" checksum: 10/8a885b38113d96138d87f6cb474ee959b7e9ab33c0c4cb1b07dcf019ec544945a2309d53d721532af020de4b3a58fb89f1026f64f42f9421aa9c3ae48a36998b languageName: node linkType: hard -"dotenv@npm:^16.3.1": - version: 16.6.1 - resolution: "dotenv@npm:16.6.1" - checksum: 10/1d1897144344447ffe62aa1a6d664f4cd2e0784e0aff787eeeec1940ded32f8e4b5b506d665134fc87157baa086fce07ec6383970a2b6d2e7985beaed6a4cc14 - languageName: node - linkType: hard - "electron-to-chromium@npm:^1.5.73": version: 1.5.105 resolution: "electron-to-chromium@npm:1.5.105" @@ -2845,15 +2574,6 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0": - version: 1.4.5 - resolution: "end-of-stream@npm:1.4.5" - dependencies: - once: "npm:^1.4.0" - checksum: 10/1e0cfa6e7f49887544e03314f9dfc56a8cb6dde910cbb445983ecc2ff426fc05946df9d75d8a21a3a64f2cecfe1bf88f773952029f46756b2ed64a24e95b1fb8 - languageName: node - linkType: hard - "enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": version: 5.17.1 resolution: "enhanced-resolve@npm:5.17.1" @@ -2922,20 +2642,6 @@ __metadata: languageName: node linkType: hard -"es-toolkit@npm:^1.39.7": - version: 1.49.0 - resolution: "es-toolkit@npm:1.49.0" - dependenciesMeta: - "@trivago/prettier-plugin-sort-imports@4.3.0": - unplugged: true - prettier-plugin-sort-re-exports@0.0.1: - unplugged: true - vitepress-plugin-sandpack@1.1.4: - unplugged: true - checksum: 10/ff0377f1fa681e6b58c06ec46cd3683c02df499f5101effb70bfbf4d69fce2e6a13889b182f68c495e25cdee31829f21dfd6094f722d4de82c546c2a32d0c670 - languageName: node - linkType: hard - "escalade@npm:^3.1.1, escalade@npm:^3.2.0": version: 3.2.0 resolution: "escalade@npm:3.2.0" @@ -3328,16 +3034,16 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.2, fast-glob@npm:^3.3.2": - version: 3.3.3 - resolution: "fast-glob@npm:3.3.3" +"fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.8" - checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad + micromatch: "npm:^4.0.4" + checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -3512,15 +3218,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^5.1.0": - version: 5.2.0 - resolution: "get-stream@npm:5.2.0" - dependencies: - pump: "npm:^3.0.0" - checksum: 10/13a73148dca795e41421013da6e3ebff8ccb7fba4d2f023fd0c6da2c166ec4e789bec9774a73a7b49c08daf2cae552f8a3e914042ac23b5f59dd278cc8f9cbfb - languageName: node - linkType: hard - "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -3631,25 +3328,6 @@ __metadata: languageName: node linkType: hard -"got@npm:^11.7.0": - version: 11.8.6 - resolution: "got@npm:11.8.6" - dependencies: - "@sindresorhus/is": "npm:^4.0.0" - "@szmarczak/http-timer": "npm:^4.0.5" - "@types/cacheable-request": "npm:^6.0.1" - "@types/responselike": "npm:^1.0.0" - cacheable-lookup: "npm:^5.0.3" - cacheable-request: "npm:^7.0.2" - decompress-response: "npm:^6.0.0" - http2-wrapper: "npm:^1.0.0-beta.5.2" - lowercase-keys: "npm:^2.0.0" - p-cancelable: "npm:^2.0.0" - responselike: "npm:^2.0.0" - checksum: 10/a30c74029d81bd5fe50dea1a0c970595d792c568e188ff8be254b5bc11e6158d1b014570772d4a30d0a97723e7dd34e7c8cc1a2f23018f60aece3070a7a5c2a5 - languageName: node - linkType: hard - "graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" @@ -3657,13 +3335,6 @@ __metadata: languageName: node linkType: hard -"grapheme-splitter@npm:^1.0.4": - version: 1.0.4 - resolution: "grapheme-splitter@npm:1.0.4" - checksum: 10/fdb2f51fd430ce881e18e44c4934ad30e59736e46213f7ad35ea5970a9ebdf7d0fe56150d15cc98230d55d2fd48c73dc6781494c38d8cf2405718366c36adb88 - languageName: node - linkType: hard - "graphemer@npm:^1.4.0": version: 1.4.0 resolution: "graphemer@npm:1.4.0" @@ -3740,13 +3411,6 @@ __metadata: languageName: node linkType: hard -"hpagent@npm:^1.2.0": - version: 1.2.0 - resolution: "hpagent@npm:1.2.0" - checksum: 10/bad186449da7e3456788a8cbae459fc6c0a855d5872a7f460c48ce4a613020d8d914839dad10047297099299c4f9e6c65a0eec3f5886af196c0a516e4ad8a845 - languageName: node - linkType: hard - "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -3761,10 +3425,10 @@ __metadata: languageName: node linkType: hard -"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 +"http-cache-semantics@npm:^4.1.0": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f languageName: node linkType: hard @@ -3779,16 +3443,6 @@ __metadata: languageName: node linkType: hard -"http2-wrapper@npm:^1.0.0-beta.5.2": - version: 1.0.3 - resolution: "http2-wrapper@npm:1.0.3" - dependencies: - quick-lru: "npm:^5.1.1" - resolve-alpn: "npm:^1.0.0" - checksum: 10/8097ee2699440c2e64bda52124990cc5b0fb347401c7797b1a0c1efd5a0f79a4ebaa68e8a6ac3e2dde5f09460c1602764da6da2412bad628ed0a3b0ae35e72d4 - languageName: node - linkType: hard - "https-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "https-proxy-agent@npm:5.0.0" @@ -4035,7 +3689,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.10.0, js-yaml@npm:^3.14.1": +"js-yaml@npm:^3.14.1": version: 3.15.1 resolution: "js-yaml@npm:3.15.1" dependencies: @@ -4125,7 +3779,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.0.0, keyv@npm:^4.5.4": +"keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -4303,13 +3957,6 @@ __metadata: languageName: node linkType: hard -"lowercase-keys@npm:^2.0.0": - version: 2.0.0 - resolution: "lowercase-keys@npm:2.0.0" - checksum: 10/1c233d2da35056e8c49fae8097ee061b8c799b2f02e33c2bf32f9913c7de8fb481ab04dab7df35e94156c800f5f34e99acbf32b21781d87c3aa43ef7b748b79e - languageName: node - linkType: hard - "lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": version: 11.5.2 resolution: "lru-cache@npm:11.5.2" @@ -4521,7 +4168,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.4": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -4538,20 +4185,6 @@ __metadata: languageName: node linkType: hard -"mimic-response@npm:^1.0.0": - version: 1.0.1 - resolution: "mimic-response@npm:1.0.1" - checksum: 10/034c78753b0e622bc03c983663b1cdf66d03861050e0c8606563d149bc2b02d63f62ce4d32be4ab50d0553ae0ffe647fc34d1f5281184c6e1e8cf4d85e8d9823 - languageName: node - linkType: hard - -"mimic-response@npm:^3.1.0": - version: 3.1.0 - resolution: "mimic-response@npm:3.1.0" - checksum: 10/7e719047612411fe071332a7498cf0448bbe43c485c0d780046c76633a771b223ff49bd00267be122cedebb897037fdb527df72335d0d0f74724604ca70b37ad - languageName: node - linkType: hard - "minimatch@npm:^10.2.2, minimatch@npm:^9.0.3 || ^10.0.1": version: 10.2.6 resolution: "minimatch@npm:10.2.6" @@ -4832,13 +4465,6 @@ __metadata: languageName: node linkType: hard -"normalize-url@npm:^6.0.1": - version: 6.1.0 - resolution: "normalize-url@npm:6.1.0" - checksum: 10/5ae699402c9d5ffa330adc348fcd6fc6e6a155ab7c811b96e30b7ecab60ceef821d8f86443869671dda71bbc47f4b9625739c82ad247e883e9aefe875bfb8659 - languageName: node - linkType: hard - "npm-install-checks@npm:^8.0.0": version: 8.0.0 resolution: "npm-install-checks@npm:8.0.0" @@ -4914,7 +4540,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -5024,22 +4650,6 @@ __metadata: languageName: node linkType: hard -"p-cancelable@npm:^2.0.0": - version: 2.1.1 - resolution: "p-cancelable@npm:2.1.1" - checksum: 10/7f1b64db17fc54acf359167d62898115dcf2a64bf6b3b038e4faf36fc059e5ed762fb9624df8ed04b25bee8de3ab8d72dea9879a2a960cd12e23c420a4aca6ed - languageName: node - linkType: hard - -"p-limit@npm:^2.2.0": - version: 2.3.0 - resolution: "p-limit@npm:2.3.0" - dependencies: - p-try: "npm:^2.0.0" - checksum: 10/84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 - languageName: node - linkType: hard - "p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" @@ -5067,13 +4677,6 @@ __metadata: languageName: node linkType: hard -"p-try@npm:^2.0.0": - version: 2.2.0 - resolution: "p-try@npm:2.2.0" - checksum: 10/f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -5252,16 +4855,6 @@ __metadata: languageName: node linkType: hard -"pump@npm:^3.0.0": - version: 3.0.4 - resolution: "pump@npm:3.0.4" - dependencies: - end-of-stream: "npm:^1.1.0" - once: "npm:^1.3.1" - checksum: 10/d043c3e710c56ffd280711e98a94e863ab334f79ea43cee0fb70e1349b2355ffd2ff287c7522e4c960a247699d5b7825f00fa090b85d6179c973be13f78a6c49 - languageName: node - linkType: hard - "punycode.js@npm:^2.3.1": version: 2.3.1 resolution: "punycode.js@npm:2.3.1" @@ -5283,13 +4876,6 @@ __metadata: languageName: node linkType: hard -"quick-lru@npm:^5.1.1": - version: 5.1.1 - resolution: "quick-lru@npm:5.1.1" - checksum: 10/a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed - languageName: node - linkType: hard - "read-cmd-shim@npm:^4.0.0": version: 4.0.0 resolution: "read-cmd-shim@npm:4.0.0" @@ -5347,13 +4933,6 @@ __metadata: languageName: node linkType: hard -"resolve-alpn@npm:^1.0.0": - version: 1.2.1 - resolution: "resolve-alpn@npm:1.2.1" - checksum: 10/744e87888f0b6fa0b256ab454ca0b9c0b80808715e2ef1f3672773665c92a941f6181194e30ccae4a8cd0adbe0d955d3f133102636d2ee0cca0119fec0bc9aec - languageName: node - linkType: hard - "resolve-dir@npm:^1.0.0, resolve-dir@npm:^1.0.1": version: 1.0.1 resolution: "resolve-dir@npm:1.0.1" @@ -5413,15 +4992,6 @@ __metadata: languageName: node linkType: hard -"responselike@npm:^2.0.0": - version: 2.0.1 - resolution: "responselike@npm:2.0.1" - dependencies: - lowercase-keys: "npm:^2.0.0" - checksum: 10/b122535466e9c97b55e69c7f18e2be0ce3823c5d47ee8de0d9c0b114aa55741c6db8bfbfce3766a94d1272e61bfb1ebf0a15e9310ac5629fbb7446a861b4fd3a - languageName: node - linkType: hard - "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -5544,12 +5114,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.2": - version: 7.8.5 - resolution: "semver@npm:7.8.5" +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.2": + version: 7.7.2 + resolution: "semver@npm:7.7.2" bin: semver: bin/semver.js - checksum: 10/9b01d2ff11e6e4a4539b7ca3c5f280c8704cb397a28504469f2ed4f00ad2194748d756647362a9712fff30984d15772ab7f083108c2fb508e2096ae9e708f22c + checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda languageName: node linkType: hard @@ -5847,16 +5417,16 @@ __metadata: languageName: node linkType: hard -"tar@npm:^7.5.3, tar@npm:^7.5.4": - version: 7.5.22 - resolution: "tar@npm:7.5.22" +"tar@npm:^7.5.4": + version: 7.5.20 + resolution: "tar@npm:7.5.20" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/129606384b3c895f422aaca48bf316357be6dc7aa35c1066c3f06c28acfff0be5b356e1b0a0be7c53a7a8945534ac06cec6d8e296d170d8a09c8bff67b29300e + checksum: 10/90a0fe423ac921197ad5eefc5e5f7ad7f42b06e80444c8c347c1e4112384cbe9cb53ade3ef71748eed3684888756869c2aeef6b6303c766101f3217e254d4be9 languageName: node linkType: hard @@ -5891,13 +5461,6 @@ __metadata: languageName: node linkType: hard -"tinylogic@npm:^2.0.0": - version: 2.0.0 - resolution: "tinylogic@npm:2.0.0" - checksum: 10/6467b1ed9b602dae035726ee3faf2682bddffb5389b42fdb4daf13878037420ed9981a572ca7db467bd26c4ab00fb4eefe654f24e35984ec017fb5e83081db97 - languageName: node - linkType: hard - "tinypool@npm:2.1.0": version: 2.1.0 resolution: "tinypool@npm:2.1.0" @@ -5921,13 +5484,6 @@ __metadata: languageName: node linkType: hard -"treeify@npm:^1.1.0": - version: 1.1.0 - resolution: "treeify@npm:1.1.0" - checksum: 10/5241976a751168fb9894a12d031299f1f6337b7f2cbd3eff22ee86e6777620352a69a1cab0d4709251317ff307eeda0dc45918850974fc44f4c7fc50e623b990 - languageName: node - linkType: hard - "trim-lines@npm:^3.0.0": version: 3.0.1 resolution: "trim-lines@npm:3.0.1" @@ -5996,13 +5552,6 @@ __metadata: languageName: node linkType: hard -"typanion@npm:^3.8.0": - version: 3.14.0 - resolution: "typanion@npm:3.14.0" - checksum: 10/5e88d9e6121ff0ec543f572152fdd1b70e9cca35406d79013ec8e08defa8ef96de5fec9e98da3afbd1eb4426b9e8e8fe423163d0b482e34a40103cab1ef29abd - languageName: node - linkType: hard - "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -6105,13 +5654,6 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~8.3.0": - version: 8.3.0 - resolution: "undici-types@npm:8.3.0" - checksum: 10/6681d2837ac75a75ac1cc46090aa2b8ddc7c6b8ecc295a6cdb06838752a730da3d8afeecf05e5ab7903160eafad3a8b6ffa1927e5ded260590f4d4fef18646d5 - languageName: node - linkType: hard - "undici@npm:^6.25.0": version: 6.28.0 resolution: "undici@npm:6.28.0" @@ -6575,7 +6117,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.5.1, yaml@npm:^2.7.1": +"yaml@npm:^2.5.1": version: 2.9.0 resolution: "yaml@npm:2.9.0" bin: From 0e2133145fed8c78fd6032eac086ed9379a3609b Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Thu, 16 Jul 2026 10:13:11 +0200 Subject: [PATCH 03/19] Remove old `allow-scripts` plugin --- .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs | 9 --------- .yarnrc.yml | 2 -- 2 files changed, 11 deletions(-) delete mode 100644 .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs diff --git a/.yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs b/.yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs deleted file mode 100644 index 05671f9..0000000 --- a/.yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable */ -//prettier-ignore -module.exports = { -name: "@yarnpkg/plugin-allow-scripts", -factory: function (require) { -var plugin=(()=>{var a=Object.create,l=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var p=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty;var u=e=>l(e,"__esModule",{value:!0});var f=e=>{if(typeof require!="undefined")return require(e);throw new Error('Dynamic require of "'+e+'" is not supported')};var g=(e,o)=>{for(var r in o)l(e,r,{get:o[r],enumerable:!0})},m=(e,o,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of s(o))!c.call(e,t)&&t!=="default"&&l(e,t,{get:()=>o[t],enumerable:!(r=i(o,t))||r.enumerable});return e},x=e=>m(u(l(e!=null?a(p(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var k={};g(k,{default:()=>d});var n=x(f("@yarnpkg/shell")),y={hooks:{afterAllInstalled:async()=>{let e=await(0,n.execute)("yarn run allow-scripts");e!==0&&process.exit(e)}}},d=y;return k;})(); -return plugin; -} -}; diff --git a/.yarnrc.yml b/.yarnrc.yml index 53bf402..cfd82e1 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -30,7 +30,5 @@ npmPreapprovedPackages: # Protect the runtime of calls to "yarn run" scripts using a local plugin. plugins: - - path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs - spec: https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js - path: ./lavamoat/plugin-allow-scripts.js - path: ./lavamoat/.runner-plugin.js From d3eb27573cee32e5af4182ed575a01356676a2d0 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Thu, 16 Jul 2026 10:14:58 +0200 Subject: [PATCH 04/19] Ignore LavaMoat folder in ESLint --- eslint.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index ac19e12..35f47ed 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,7 @@ import vitest from '@metamask/eslint-config-vitest'; const config = createConfig([ { - ignores: ['dist/', 'docs/', '.yarn/'], + ignores: ['dist/', 'docs/', '.yarn/', 'lavamoat/'], }, { From 965965077669e3752c6fc3a3faedc3a55c203e97 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Thu, 16 Jul 2026 10:16:58 +0200 Subject: [PATCH 05/19] Add `@yarnpkg/shell` to depcheck ignores --- .depcheckrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.depcheckrc.json b/.depcheckrc.json index 1d3a983..d9563e8 100644 --- a/.depcheckrc.json +++ b/.depcheckrc.json @@ -10,6 +10,7 @@ "@vitest/coverage-istanbul", "@vitest/eslint-plugin", "@yarnpkg/types", + "@yarnpkg/shell", "eslint-config-*", "eslint-import-resolver-typescript", "eslint-plugin-*", From 7ad86ba24a134160d83770740b4d0a6dbf1b51bf Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Mon, 17 Aug 2026 14:50:35 +0200 Subject: [PATCH 06/19] Apply latest version of @lavamoat/harden --- .yarnrc.yml | 3 + lavamoat/.runner-plugin.js | 253 ++++++++++++++++++++++--------------- 2 files changed, 157 insertions(+), 99 deletions(-) diff --git a/.yarnrc.yml b/.yarnrc.yml index cfd82e1..41669f3 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -7,6 +7,9 @@ compressionLevel: mixed enableGlobalCache: false +# Enable hardened mode to validate lockfile content against remote registries. +enableHardenedMode: true + enableScripts: false enableTelemetry: false diff --git a/lavamoat/.runner-plugin.js b/lavamoat/.runner-plugin.js index ccd7295..9acee99 100755 --- a/lavamoat/.runner-plugin.js +++ b/lavamoat/.runner-plugin.js @@ -17,6 +17,7 @@ module.exports = { name: '@yarnpkg/plugin-runner', factory: function (/** @type {NodeJS.Require} */ require) { + const { tmpdir } = require('node:os') return { hooks: { /** @type {WrapScriptExecutionHook} */ @@ -25,25 +26,26 @@ module.exports = { project, locator, scriptName, - extra, + extra ) => { - const path = require('node:path'); - const fs = require('node:fs'); - const workspace = project.tryWorkspaceByLocator(locator); + const path = require('node:path') + const fs = require('node:fs') + const workspace = project.tryWorkspaceByLocator(locator) if (!workspace) { - // a script is being executed outside of a workspace context, so we can't apply any custom logic + // a script is being executed outside of a workspace context, so we + // can't apply any custom logic. // This is the case when a postinstal is running. // "Do nothing" - return the original executor immediately // without running any custom plugin logic or reading manifests. // TODO: implement wrapping these scripts with reasonable defaults - return executor; + return executor } - const pkgJson = workspace.manifest.raw; + const pkgJson = workspace.manifest.raw const binFolder = - extra.env.BERRY_BIN_FOLDER || `node_modules${path.sep}.bin`; + extra.env.BERRY_BIN_FOLDER || `node_modules${path.sep}.bin` const wrapper = makeRunScriptWrapper( { @@ -51,31 +53,36 @@ module.exports = { scriptPayload: extra.script, projectRoot: extra.cwd, pathBinMatcher: (fragment) => { - return fragment.endsWith(binFolder); + return fragment.endsWith(binFolder) }, customizePermissionsConfig: addMandatoryReads, readScriptsConfig: () => { - return pkgJson.scriptsConfig; + return pkgJson.scriptsConfig }, }, { readFileSync: fs.readFileSync, pathJoin: path.join, pathDelimiter: path.delimiter, - }, - ); - - const newEnv = wrapper.processEnv(extra.env); + tmpdir, + realpathSync: fs.realpathSync, + } + ) + + // extra.env is a reference to the mutable object, but a different variable + // containing that reference is used within execute, so we must amend not + // replace it. + const newEnv = wrapper.processEnv(extra.env) for (const key of Object.keys(extra.env)) { - delete extra.env[key]; + delete extra.env[key] } - Object.assign(extra.env, newEnv); - return executor; + Object.assign(extra.env, newEnv) + return executor }, }, - }; + } }, -}; +} /** * @param {Record} configOptions @@ -83,30 +90,13 @@ module.exports = { */ function addMandatoryReads(configOptions, _env) { if (!configOptions['--permission']) { - return; - } - if (!Array.isArray(configOptions['--allow-fs-read'])) { - configOptions['--allow-fs-read'] = []; + return } - if (!Array.isArray(configOptions['--allow-fs-write'])) { - configOptions['--allow-fs-write'] = []; - } - - // figure out the /tmp dir for the current platform - - const tmpdir = - process.platform === 'win32' - ? process.env.TEMP || '' // make typescript shut up - : '/tmp'; - // yarn script execution makes heavy use of temporary dirs - configOptions['--allow-fs-read'].push(tmpdir); - configOptions['--allow-fs-write'].push(tmpdir); + configOptions['--allow-fs-tmp'] = true // yarn always uses tmp dirs. } -/// -/** - * @typedef {Record} ConfigOptions - */ +;; +/// /** * @param {MakeRunScriptWrapperOptions} param0 @@ -122,13 +112,13 @@ function makeRunScriptWrapper( customizePermissionsConfig, readScriptsConfig, }, - { readFileSync, pathJoin, pathDelimiter }, + { readFileSync, pathJoin, pathDelimiter, tmpdir, realpathSync } ) { - const DEFAULT_PERMISSION_KEY = '#default'; + const DEFAULT_PERMISSION_KEY = '#default' /** @param {string} filePath */ function readJsonFile(filePath) { - return JSON.parse(readFileSync(filePath, 'utf8')); + return JSON.parse(readFileSync(filePath, 'utf8')) } /** @@ -143,30 +133,91 @@ function makeRunScriptWrapper( projectRoot, }) { if (!scriptsConfig) { - return {}; + return {} } const configName = - scriptsConfig[scriptName] || scriptsConfig[DEFAULT_PERMISSION_KEY]; + scriptsConfig[scriptName] || scriptsConfig[DEFAULT_PERMISSION_KEY] // config needs to be optional, because it's opt-in first and specifying a default turns it opt-out. if (!configName) { - return {}; + return {} } - const configPath = pathJoin(projectRoot, configName); - let conf; + const configPath = pathJoin(projectRoot, configName) + let conf try { - conf = readJsonFile(configPath); + conf = readJsonFile(configPath) if (typeof conf !== 'object' || conf === null) { - throw Error(`Expected an object, got ${typeof conf}`); + throw Error(`Expected an object, got ${typeof conf}`) } } catch (err) { - const message = err instanceof Error ? err.message : String(err); + const message = err instanceof Error ? err.message : String(err) throw Error( `[LavaMoat] Error loading script config file "${configPath}": ${message}`, - { cause: err }, - ); + { cause: err } + ) + } + return conf + } + + /** + * Adds features we'd want in Node.js permissions model and intend to + * eventually upstream + * + * @param {ConfigOptions} configOptions + * @param {NodeJS.ProcessEnv} env + * @returns {void} + */ + function permissionsModelCompatibilityExtensions(configOptions, env) { + // 1. support env variables as values in allow-fs-* + /** + * @param {string} value + * @returns {string} + */ + const replaceEnvVar = (value) => { + const envVarMatch = value.match(/^\$([A-Z_][A-Z0-9_]*)$/i) + if (envVarMatch) { + const envVarName = envVarMatch[1] + if (env[envVarName] !== undefined) { + return env[envVarName] + } else { + console.error( + `[LavaMoat] Environment variable "${envVarName}" referenced in config but not found in environment` + ) + } + } + return value + } + + for (const key of ['--allow-fs-read', '--allow-fs-write']) { + if (Array.isArray(configOptions[key])) { + configOptions[key] = configOptions[key].map(replaceEnvVar) + } + } + + // 2. tmp write - crossplatform + if (configOptions['--allow-fs-tmp'] === true) { + delete configOptions['--allow-fs-tmp'] + if (configOptions['--allow-fs-write']) { + if (typeof configOptions['--allow-fs-write'] === 'string') { + configOptions['--allow-fs-write'] = [ + configOptions['--allow-fs-write'], + ] + } + if (configOptions['--allow-fs-write'] === true) { + return // none of this matters + } + } else { + // do this for both undefined and false + configOptions['--allow-fs-write'] = [] + } + const tmp = tmpdir() + configOptions['--allow-fs-write'].push(tmp) + // because macos is being weird + const tmpRealPath = realpathSync(tmp) + if (tmpRealPath !== tmp) { + configOptions['--allow-fs-write'].push(tmpRealPath) + } } - return conf; } /** @param {ConfigOptions} configOptions */ @@ -174,15 +225,15 @@ function makeRunScriptWrapper( return Object.entries(configOptions) .map(([arg, value]) => { if (typeof value === 'boolean') { - return value ? arg : ''; + return value ? arg : '' } else if (Array.isArray(value)) { - return value.map((v) => `${arg}="${v}"`).join(' '); + return value.map((v) => `${arg}="${v}"`).join(' ') } else { - return `${arg}="${value}"`; + return `${arg}="${value}"` } }) .filter(Boolean) - .join(' '); + .join(' ') } /** @@ -194,14 +245,16 @@ function makeRunScriptWrapper( */ function installNodeOptions(existingOptions, configOptions, env) { if (!configOptions) { - return existingOptions || ''; + return existingOptions || '' } - customizePermissionsConfig(configOptions, env); + customizePermissionsConfig(configOptions, env) - const confOption = makeFlagsFromConfig(configOptions); + permissionsModelCompatibilityExtensions(configOptions, env) - return `${existingOptions || ''} ${confOption.trim()}`.trim(); + const confOption = makeFlagsFromConfig(configOptions) + + return `${existingOptions || ''} ${confOption.trim()}`.trim() } /** @@ -212,93 +265,93 @@ function makeRunScriptWrapper( * @returns {NodeJS.ProcessEnv} */ function filterEnv(env, lavamoatDir) { - const banFilePath = pathJoin(lavamoatDir, '.env.ban.json'); - let banConfig; + const banFilePath = pathJoin(lavamoatDir, '.env.ban.json') + let banConfig try { - banConfig = readJsonFile(banFilePath); + banConfig = readJsonFile(banFilePath) } catch (err) { - const message = err instanceof Error ? err.message : String(err); + const message = err instanceof Error ? err.message : String(err) console.error( - `[LavaMoat] Warning: Failed to read .env.ban.json: ${message}.`, - ); - return env; + `[LavaMoat] Warning: Failed to read .env.ban.json: ${message}.` + ) + return env } - let banKeywords = []; + let banKeywords = [] try { if (Array.isArray(banConfig)) { - banKeywords.push(...banConfig); + banKeywords.push(...banConfig) } else { - throw Error(`Expected .env.ban.json to contain an array of keywords`); + throw Error(`Expected .env.ban.json to contain an array of keywords`) } } catch (err) { - const message = err instanceof Error ? err.message : String(err); + const message = err instanceof Error ? err.message : String(err) console.error( - `[LavaMoat] Warning: Failed to read .env.ban.json: ${message}.`, - ); - return env; + `[LavaMoat] Warning: Failed to read .env.ban.json: ${message}.` + ) + return env } /** @type {NodeJS.ProcessEnv} */ - const filteredEnv = {}; - const bannedEnv = []; - banKeywords = banKeywords.map((keyword) => keyword.toLowerCase()); + const filteredEnv = {} + const bannedEnv = [] + banKeywords = banKeywords.map((keyword) => keyword.toLowerCase()) for (const [key, value] of Object.entries(env)) { if ( !key.toLowerCase().startsWith('npm_config') && banKeywords.some((keyword) => key.toLowerCase().includes(keyword)) ) { - bannedEnv.push(key); + bannedEnv.push(key) } else { - filteredEnv[key] = value; + filteredEnv[key] = value } } if (bannedEnv.length > 0) { console.error( - `[LavaMoat] Warning: The following environment variables were banned: ${bannedEnv.join(', ')}`, - ); + `[LavaMoat] Warning: The following environment variables were banned: ${bannedEnv.join(', ')}` + ) } - return filteredEnv; + return filteredEnv } /** @param {string} PATH */ function envPathOpinions(PATH) { - const pathFragments = PATH.split(pathDelimiter); + const pathFragments = PATH.split(pathDelimiter) // This is to eliminate bin confusion attacks. // Find node_modules/.bin and remove it, put it on the end that gets looked up last when looking for a name in the path. /** @type {string[]} */ - const filteredFragments = []; + const filteredFragments = [] /** @type {string[]} */ - const nodeModulesBinFragments = []; + const nodeModulesBinFragments = [] for (const fragment of pathFragments) { if (pathBinMatcher(fragment)) { - nodeModulesBinFragments.push(fragment); + nodeModulesBinFragments.push(fragment) } else { - filteredFragments.push(fragment); + filteredFragments.push(fragment) } } // Why would there be multiple bin fragments? In a npm workspace, local bin and workspace root bin is added - filteredFragments.push(...nodeModulesBinFragments); - return filteredFragments.join(pathDelimiter); + filteredFragments.push(...nodeModulesBinFragments) + return filteredFragments.join(pathDelimiter) } return { processEnv: (existingEnv) => { - const scriptsConfig = readScriptsConfig(projectRoot); + const scriptsConfig = readScriptsConfig(projectRoot) const config = readConfig({ scriptsConfig, scriptName, projectRoot, - }); + }) // Smell: Windows environment variables are case-insensitive, but Node's process.env // might expose it as 'Path' instead of 'PATH'. Checking both ensures it doesn't get wiped out. - const existingPath = existingEnv.PATH || existingEnv.Path || ''; + const existingPath = existingEnv.PATH || existingEnv.Path || '' - const lavamoatDir = pathJoin(projectRoot, 'lavamoat'); + const lavamoatDir = pathJoin(projectRoot, 'lavamoat') const fixedEnv = { ...filterEnv(existingEnv, lavamoatDir), @@ -306,10 +359,12 @@ function makeRunScriptWrapper( NODE_OPTIONS: installNodeOptions( existingEnv.NODE_OPTIONS, config.nodeOptions, - existingEnv, + existingEnv ), - }; - return fixedEnv; + } + return fixedEnv }, - }; + } } + + From 755e4c3bf9c447ab40db6d00f3af4bfdd9e94c08 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 10:23:12 +0200 Subject: [PATCH 07/19] Ignore LavaMoat folder in Oxfmt --- .oxfmtrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.oxfmtrc.json b/.oxfmtrc.json index a8a63ac..eaf60bd 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -1,6 +1,6 @@ { "$schema": "./node_modules/oxfmt/configuration_schema.json", - "ignorePatterns": [".yarnrc.yml"], + "ignorePatterns": [".yarnrc.yml", "lavamoat"], "printWidth": 80, "quoteProps": "as-needed", "singleQuote": true, From 8948c06c2a26c0041a0a7f12f8a55eacfd9d18e1 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 10:38:30 +0200 Subject: [PATCH 08/19] Set enableMirror: false to avoid writing to global cache --- .yarnrc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.yarnrc.yml b/.yarnrc.yml index 41669f3..86cc38b 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -7,6 +7,8 @@ compressionLevel: mixed enableGlobalCache: false +enableMirror: false + # Enable hardened mode to validate lockfile content against remote registries. enableHardenedMode: true From ca0e7ede8866a413fdafbb4ea45cd04339015347 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 10:39:40 +0200 Subject: [PATCH 09/19] Add docs to `enableMirror` option --- .yarnrc.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.yarnrc.yml b/.yarnrc.yml index 86cc38b..109a616 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -7,11 +7,12 @@ compressionLevel: mixed enableGlobalCache: false -enableMirror: false - # Enable hardened mode to validate lockfile content against remote registries. enableHardenedMode: true +# Disable Yarn's mirror feature to avoid writing to the global cache. +enableMirror: false + enableScripts: false enableTelemetry: false From 1ef1fe57a8287f50e4a22b27783aa9744d1eb8e0 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 11:17:32 +0200 Subject: [PATCH 10/19] Fix Vitest and ATTW --- lavamoat/scripts.test.json | 14 ++++++++++++++ package.json | 9 ++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 lavamoat/scripts.test.json diff --git a/lavamoat/scripts.test.json b/lavamoat/scripts.test.json new file mode 100644 index 0000000..5f9e1f6 --- /dev/null +++ b/lavamoat/scripts.test.json @@ -0,0 +1,14 @@ +{ + "notes": "Should prevent basic malicious behavior of writing to locations outside the project and sending network requests, but not break any of the advanced packages in use. Everything below the net permission can be used to bypass the restrictions by a more sophisticated attacker.", + "nodeOptions": { + "--permission": true, + "--allow-fs-read": ["/"], + "--allow-fs-write": ["./", "$GITHUB_STEP_SUMMARY"], + "--allow-net": false, + "--allow-child-process": true, + "--allow-worker": true, + "--allow-addons": true, + "--allow-wasi": true, + "--allow-inspector": false + } +} diff --git a/package.json b/package.json index 3d4c2dd..c0bbec7 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,9 @@ "lint:fix": "yarn lint:eslint --fix && yarn lint:constraints --fix && yarn lint:misc --write && yarn lint:dependencies:fix && yarn lint:changelog --fix", "lint:misc": "oxfmt --ignore-path .gitignore", "prepack": "./scripts/prepack.sh", - "test": "vitest && attw --pack", - "test:watch": "vitest --watch" + "test": "vitest && yarn test:package", + "test:watch": "vitest --watch", + "test:package": "yarn pack --out .yarn/package.tgz && attw .yarn/package.tgz" }, "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", @@ -102,6 +103,8 @@ } }, "scriptsConfig": { - "#default": "lavamoat/scripts.loose.json" + "#default": "lavamoat/scripts.loose.json", + "test": "lavamoat/scripts.test.json", + "test:watch": "lavamoat/scripts.test.json" } } From e541949cd817b7770b7350742dfb25d42b8f28d1 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 13:06:55 +0200 Subject: [PATCH 11/19] Restrict permissions where possible --- .yarnrc.yml | 4 ++++ lavamoat/scripts.lint.json | 14 ++++++++++++++ lavamoat/scripts.test.json | 4 ++-- lavamoat/scripts.yarn.json | 14 ++++++++++++++ package.json | 16 +++++++++++++--- 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 lavamoat/scripts.lint.json create mode 100644 lavamoat/scripts.yarn.json diff --git a/.yarnrc.yml b/.yarnrc.yml index 109a616..6659c0c 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -17,6 +17,10 @@ enableScripts: false enableTelemetry: false +# Despite `enableGlobalCache` and `enableMirror` being `false`, Yarn is still +# writing to the global folder. +globalFolder: .yarn/global + logFilters: - code: YN0004 level: discard diff --git a/lavamoat/scripts.lint.json b/lavamoat/scripts.lint.json new file mode 100644 index 0000000..0609ae5 --- /dev/null +++ b/lavamoat/scripts.lint.json @@ -0,0 +1,14 @@ +{ + "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit.", + "nodeOptions": { + "--permission": true, + "--allow-fs-read": ["./"], + "--allow-fs-write": ["./"], + "--allow-child-process": false, + "--allow-net": false, + "--allow-worker": false, + "--allow-addons": true, + "--allow-wasi": false, + "--allow-inspector": false + } +} diff --git a/lavamoat/scripts.test.json b/lavamoat/scripts.test.json index 5f9e1f6..f4efb41 100644 --- a/lavamoat/scripts.test.json +++ b/lavamoat/scripts.test.json @@ -6,9 +6,9 @@ "--allow-fs-write": ["./", "$GITHUB_STEP_SUMMARY"], "--allow-net": false, "--allow-child-process": true, - "--allow-worker": true, + "--allow-worker": false, "--allow-addons": true, - "--allow-wasi": true, + "--allow-wasi": false, "--allow-inspector": false } } diff --git a/lavamoat/scripts.yarn.json b/lavamoat/scripts.yarn.json new file mode 100644 index 0000000..941aa10 --- /dev/null +++ b/lavamoat/scripts.yarn.json @@ -0,0 +1,14 @@ +{ + "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit.", + "nodeOptions": { + "--permission": true, + "--allow-fs-read": ["/"], + "--allow-fs-write": ["./"], + "--allow-child-process": true, + "--allow-net": false, + "--allow-worker": false, + "--allow-addons": false, + "--allow-wasi": false, + "--allow-inspector": false + } +} diff --git a/package.json b/package.json index c0bbec7..8772b8b 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,10 @@ "lint": "yarn lint:eslint && yarn lint:constraints && yarn lint:misc --check && yarn lint:dependencies --check && yarn lint:changelog", "lint:changelog": "auto-changelog validate --formatter oxfmt", "lint:constraints": "yarn constraints", - "lint:dependencies": "depcheck && yarn dedupe --check", - "lint:dependencies:fix": "depcheck && yarn dedupe", + "lint:dependencies": "yarn lint:dependencies:depcheck && yarn lint:dependencies:dedupe --check", + "lint:dependencies:depcheck": "depcheck", + "lint:dependencies:dedupe": "yarn dedupe", + "lint:dependencies:fix": "yarn lint:dependencies:depcheck && yarn lint:dependencies:dedupe", "lint:eslint": "eslint .", "lint:fix": "yarn lint:eslint --fix && yarn lint:constraints --fix && yarn lint:misc --write && yarn lint:dependencies:fix && yarn lint:changelog --fix", "lint:misc": "oxfmt --ignore-path .gitignore", @@ -103,7 +105,15 @@ } }, "scriptsConfig": { - "#default": "lavamoat/scripts.loose.json", + "#default": "lavamoat/scripts.strict.json", + "lint": "lavamoat/scripts.yarn.json", + "lint:changelog": "lavamoat/scripts.lint.json", + "lint:constraints": "lavamoat/scripts.yarn.json", + "lint:dependencies": "lavamoat/scripts.yarn.json", + "lint:dependencies:dedupe": "lavamoat/scripts.yarn.json", + "lint:eslint": "lavamoat/scripts.lint.json", + "lint:fix": "lavamoat/scripts.yarn.json", + "lint:misc": "lavamoat/scripts.lint.json", "test": "lavamoat/scripts.test.json", "test:watch": "lavamoat/scripts.test.json" } From 7a76691bbdad0ff97f6884b959d2ec73ca6a5780 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 13:15:09 +0200 Subject: [PATCH 12/19] Enable --allow-net for Yarn config --- lavamoat/scripts.yarn.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lavamoat/scripts.yarn.json b/lavamoat/scripts.yarn.json index 941aa10..34dbcf7 100644 --- a/lavamoat/scripts.yarn.json +++ b/lavamoat/scripts.yarn.json @@ -5,7 +5,7 @@ "--allow-fs-read": ["/"], "--allow-fs-write": ["./"], "--allow-child-process": true, - "--allow-net": false, + "--allow-net": true, "--allow-worker": false, "--allow-addons": false, "--allow-wasi": false, From d4f2e5069697d639fbd2e3d52601a84dc4718c0a Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 14:14:26 +0200 Subject: [PATCH 13/19] Bump auto-changelog --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 8772b8b..da13ab6 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@arethetypeswrong/cli": "^0.15.3", "@lavamoat/allow-scripts": "^5.1.0", "@lavamoat/preinstall-always-fail": "^2.0.0", - "@metamask/auto-changelog": "^6.1.0", + "@metamask/auto-changelog": "^6.2.1", "@metamask/eslint-config": "^15.0.0", "@metamask/eslint-config-nodejs": "^15.0.0", "@metamask/eslint-config-typescript": "^15.0.0", diff --git a/yarn.lock b/yarn.lock index fc1d771..0dec19c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -519,9 +519,9 @@ __metadata: languageName: node linkType: hard -"@metamask/auto-changelog@npm:^6.1.0": - version: 6.1.0 - resolution: "@metamask/auto-changelog@npm:6.1.0" +"@metamask/auto-changelog@npm:^6.2.1": + version: 6.2.1 + resolution: "@metamask/auto-changelog@npm:6.2.1" dependencies: "@octokit/rest": "npm:^20.0.0" diff: "npm:^5.0.0" @@ -538,7 +538,7 @@ __metadata: optional: true bin: auto-changelog: dist/cli.mjs - checksum: 10/d4b086ea609f1395e111d8d124d74ac94e31a872f26eba5b65906f6e634f61e328264c940e7a603cb823d58a7140f8eeafec4521b85ee6584917e2c5ac90b684 + checksum: 10/88f5bc63ef5003b3e4f88ebf018229ce5e701283cadee1dcbd37f869541a1102ba6a8a96fd54993863e3578c8b79f0c6e0242e4afd08c58d5db529bc75dbaf2c languageName: node linkType: hard @@ -612,7 +612,7 @@ __metadata: "@arethetypeswrong/cli": "npm:^0.15.3" "@lavamoat/allow-scripts": "npm:^5.1.0" "@lavamoat/preinstall-always-fail": "npm:^2.0.0" - "@metamask/auto-changelog": "npm:^6.1.0" + "@metamask/auto-changelog": "npm:^6.2.1" "@metamask/eslint-config": "npm:^15.0.0" "@metamask/eslint-config-nodejs": "npm:^15.0.0" "@metamask/eslint-config-typescript": "npm:^15.0.0" From cd1ff8d37dbb94341a22a14e4fc21ce58d4b0a38 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 15:03:06 +0200 Subject: [PATCH 14/19] Update lavamoat/scripts.lint.json Co-authored-by: Zbyszek Tenerowicz --- lavamoat/scripts.lint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lavamoat/scripts.lint.json b/lavamoat/scripts.lint.json index 0609ae5..046d032 100644 --- a/lavamoat/scripts.lint.json +++ b/lavamoat/scripts.lint.json @@ -1,5 +1,5 @@ { - "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit.", + "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit. Do not allow more for all other linter scripts.", "nodeOptions": { "--permission": true, "--allow-fs-read": ["./"], From 731b12b246cba828044c148ca64ea10f1bcfcf6d Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 15:05:28 +0200 Subject: [PATCH 15/19] Update scripts.strict.json description --- lavamoat/scripts.strict.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lavamoat/scripts.strict.json b/lavamoat/scripts.strict.json index 40a8159..cf7a340 100644 --- a/lavamoat/scripts.strict.json +++ b/lavamoat/scripts.strict.json @@ -1,5 +1,5 @@ { - "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit.", + "notes": "Denies all powerful IO capabilities. This provides a strict default and if you need a script to have more permissions, choose another scripts.*.json file instead of editing this one.", "nodeOptions": { "--permission": true, "--allow-fs-read": ["./"], From d05cb0076eb0e45f96fc932cbff2ac95375c347d Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Tue, 18 Aug 2026 15:06:59 +0200 Subject: [PATCH 16/19] Update scripts.yarn.json description --- lavamoat/scripts.yarn.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lavamoat/scripts.yarn.json b/lavamoat/scripts.yarn.json index 34dbcf7..a5c243d 100644 --- a/lavamoat/scripts.yarn.json +++ b/lavamoat/scripts.yarn.json @@ -1,5 +1,5 @@ { - "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit.", + "notes": "Use this one ONLY for scripts that are only creating nested Yarn processes, e.g., a composition of multiple other scripts via `yarn something && yarn something-else`.", "nodeOptions": { "--permission": true, "--allow-fs-read": ["/"], From 341b3e47060ad81bf919320c2b59414d3eee416b Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Wed, 19 Aug 2026 11:13:08 +0200 Subject: [PATCH 17/19] Fix NODE_OPTIONS inheritance --- lavamoat/.runner-plugin.js | 2 +- lavamoat/scripts.lint.json | 3 ++- lavamoat/scripts.loose.json | 1 + lavamoat/scripts.strict.json | 1 + lavamoat/scripts.test.json | 1 + lavamoat/scripts.yarn.json | 3 ++- 6 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lavamoat/.runner-plugin.js b/lavamoat/.runner-plugin.js index 9acee99..2e41219 100755 --- a/lavamoat/.runner-plugin.js +++ b/lavamoat/.runner-plugin.js @@ -254,7 +254,7 @@ function makeRunScriptWrapper( const confOption = makeFlagsFromConfig(configOptions) - return `${existingOptions || ''} ${confOption.trim()}`.trim() + return confOption.trim() } /** diff --git a/lavamoat/scripts.lint.json b/lavamoat/scripts.lint.json index 046d032..13d43fc 100644 --- a/lavamoat/scripts.lint.json +++ b/lavamoat/scripts.lint.json @@ -1,10 +1,11 @@ { "notes": "Denies all powerful IO capabilities that a linter script should not need. If a script needs more permissions, copy this file and edit. Do not allow more for all other linter scripts.", "nodeOptions": { + "--disable-warning": "SecurityWarning", "--permission": true, "--allow-fs-read": ["./"], "--allow-fs-write": ["./"], - "--allow-child-process": false, + "--allow-child-process": true, "--allow-net": false, "--allow-worker": false, "--allow-addons": true, diff --git a/lavamoat/scripts.loose.json b/lavamoat/scripts.loose.json index 58cf05b..35609b1 100644 --- a/lavamoat/scripts.loose.json +++ b/lavamoat/scripts.loose.json @@ -1,6 +1,7 @@ { "notes": "Should prevent basic malicious behavior of writing to locations outside the project and sending network requests, but not break any of the advanced packages in use. Everything below the net permission can be used to bypass the restrictions by a more sophisticated attacker.", "nodeOptions": { + "--disable-warning": "SecurityWarning", "--permission": true, "--allow-fs-read": ["/"], "--allow-fs-write": ["./"], diff --git a/lavamoat/scripts.strict.json b/lavamoat/scripts.strict.json index cf7a340..3e381f4 100644 --- a/lavamoat/scripts.strict.json +++ b/lavamoat/scripts.strict.json @@ -1,6 +1,7 @@ { "notes": "Denies all powerful IO capabilities. This provides a strict default and if you need a script to have more permissions, choose another scripts.*.json file instead of editing this one.", "nodeOptions": { + "--disable-warning": "SecurityWarning", "--permission": true, "--allow-fs-read": ["./"], "--allow-fs-write": ["./"], diff --git a/lavamoat/scripts.test.json b/lavamoat/scripts.test.json index f4efb41..52e20e5 100644 --- a/lavamoat/scripts.test.json +++ b/lavamoat/scripts.test.json @@ -1,6 +1,7 @@ { "notes": "Should prevent basic malicious behavior of writing to locations outside the project and sending network requests, but not break any of the advanced packages in use. Everything below the net permission can be used to bypass the restrictions by a more sophisticated attacker.", "nodeOptions": { + "--disable-warning": "SecurityWarning", "--permission": true, "--allow-fs-read": ["/"], "--allow-fs-write": ["./", "$GITHUB_STEP_SUMMARY"], diff --git a/lavamoat/scripts.yarn.json b/lavamoat/scripts.yarn.json index a5c243d..9ac9e44 100644 --- a/lavamoat/scripts.yarn.json +++ b/lavamoat/scripts.yarn.json @@ -1,11 +1,12 @@ { "notes": "Use this one ONLY for scripts that are only creating nested Yarn processes, e.g., a composition of multiple other scripts via `yarn something && yarn something-else`.", "nodeOptions": { + "--disable-warning": "SecurityWarning", "--permission": true, "--allow-fs-read": ["/"], "--allow-fs-write": ["./"], "--allow-child-process": true, - "--allow-net": true, + "--allow-net": false, "--allow-worker": false, "--allow-addons": false, "--allow-wasi": false, From c93e854c2e1e02ff1244a22257192056a30e06a8 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Wed, 19 Aug 2026 11:16:59 +0200 Subject: [PATCH 18/19] Fix test config --- package.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index da13ab6..3e49933 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,9 @@ "lint:fix": "yarn lint:eslint --fix && yarn lint:constraints --fix && yarn lint:misc --write && yarn lint:dependencies:fix && yarn lint:changelog --fix", "lint:misc": "oxfmt --ignore-path .gitignore", "prepack": "./scripts/prepack.sh", - "test": "vitest && yarn test:package", - "test:watch": "vitest --watch", + "test": "yarn test:vitest && yarn test:package", + "test:vitest": "vitest", + "test:watch": "yarn test:vitest --watch", "test:package": "yarn pack --out .yarn/package.tgz && attw .yarn/package.tgz" }, "devDependencies": { @@ -114,7 +115,10 @@ "lint:eslint": "lavamoat/scripts.lint.json", "lint:fix": "lavamoat/scripts.yarn.json", "lint:misc": "lavamoat/scripts.lint.json", - "test": "lavamoat/scripts.test.json", + "prepack": "lavamoat/scripts.yarn.json", + "test": "lavamoat/scripts.yarn.json", + "test:vitest": "lavamoat/scripts.test.json", + "test:package": "lavamoat/scripts.test.json", "test:watch": "lavamoat/scripts.test.json" } } From 228265ecae1ba1d1b170268def9dbe4c71116963 Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Wed, 19 Aug 2026 12:17:35 +0200 Subject: [PATCH 19/19] Add lint:dependencies:fix config --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 3e49933..32a7c7e 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "lint:changelog": "lavamoat/scripts.lint.json", "lint:constraints": "lavamoat/scripts.yarn.json", "lint:dependencies": "lavamoat/scripts.yarn.json", + "lint:dependencies:fix": "lavamoat/scripts.yarn.json", "lint:dependencies:dedupe": "lavamoat/scripts.yarn.json", "lint:eslint": "lavamoat/scripts.lint.json", "lint:fix": "lavamoat/scripts.yarn.json",