Conversation
Add the `LavaMoat/harden` setup, based on MetaMask/metamask-module-template#335. This introduces a `lavamoat/` directory with config files containing secure defaults for running scripts (`scripts.strict.json`, `scripts.loose.json`, and `scripts.skills.json`), plus a banned environment variable list, and a Yarn runner plugin that applies them. The plugin wraps every `yarn run` script with Node's permission model, restricting filesystem, network, child process, worker, addon, WASI, and inspector access, filters sensitive environment variables out of the script environment, and moves `node_modules/.bin` to the end of `PATH` to prevent bin confusion attacks. Each workspace now declares `scriptsConfig.#default` pointing at the strict config, enforced by a new Yarn constraint. Yarn hardened mode is enabled, `.npmrc` and `.yarnrc` are added to make accidental npm or Yarn 1 usage safe, and Node is pinned to 26 since the permission model requires a recent runtime.
Mrtenz
force-pushed
the
mrtenz/harden
branch
from
September 28, 2026 12:35
909acbc to
df7418b
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
4 tasks
pull Bot
pushed a commit
to Reality2byte/core
that referenced
this pull request
Sep 29, 2026
## Explanation Modern versions of Node.js support running TypeScript files by default, so we can drop the `tsx` dependency. This is in preparation for MetaMask#9937, as `tsx` requests too many permissions by default. ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> ## Checklist - [ ] I've updated the test suite for new or updated code as appropriate - [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Wide CI and developer-tooling surface area depends on experimental Node TypeScript flags and the custom resolver; regressions would break lint, type generation, and workflows rather than shipped wallet logic. > > **Overview** > Replaces **`tsx`** across the monorepo with **Node.js** running TypeScript directly, using `--experimental-transform-types` and a new **`scripts/resolver/register.ts`** hook so existing `.js` import paths and some package resolutions (e.g. `@metamask/utils`) still work at runtime. > > Root and workspace **`package.json`** scripts for lint, messenger action types, changelog/codeowners helpers, and similar tooling now invoke `node` (with the resolver where needed). **`tsx`** is removed from devDependencies repo-wide, LavaMoat drops **`tsx>esbuild`**, and GitHub Actions call yarn scripts like **`get-changed-workspaces`** and **`close-stale-release-prs`** instead of `yarn tsx scripts/...`. > > **`messenger-cli`** and **`platform-api-docs`** tests were updated to spawn the CLI the same way CI does; **`bridge-controller`** / **`bridge-status-controller`** align on **`messenger-cli`** scripts (replacing the old generate-method-action-types entry), with a regenerated ordering tweak in bridge-status method action types. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 20ac37f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
Scripts run through
yarn runcurrently execute with the full ambient authority of the developer's shell: unrestricted filesystem access, network access, the ability to spawn child processes, and access to every environment variable including credentials. A compromised dependency that gets to run any lifecycle or package script therefore has a straightforward path to exfiltrating secrets or tampering with files outside the repository.This PR integrates the
LavaMoat/hardensetup, ported fromMetaMask/metamask-module-template.It adds a
lavamoat/directory containing:scripts.strict.json(deny all powerful IO capabilities),scripts.loose.json(a more permissive variant for scripts that genuinely need native capabilities), andscripts.skills.json(used byskills:postinstall)..env.ban.json— a list of keywords used to filter sensitive environment variables out of the script environment..runner-plugin.js— a Yarn 4 plugin that hookswrapScriptExecutionand applies the above. For every script it resolves the matching config from the workspace'sscriptsConfigfield, translates it into Node's permission model flags viaNODE_OPTIONS, strips banned environment variables, and movesnode_modules/.binto the end ofPATHto eliminate bin confusion attacks.plugin-allow-scripts.js— the LavaMoat allow-scripts plugin, now vendored locally rather than fetched from a remote URL at install time.Every workspace declares
scriptsConfig.#defaultpointing at the strict config, and a new Yarn constraint inyarn.config.cjsenforces that this stays in place for newly added packages.Some changes whose purpose may not be obvious:
.nvmrcis pinned to Node 26 — the permission model flags used here require a recent runtime..npmrcand.yarnrcare added — these make accidental use of npm or Yarn 1 safe (ignore-scripts,offline), since neither honours the Yarn 4 plugin.enableHardenedMode: truein.yarnrc.ymlvalidates lockfile content against the remote registries.enableMirror: falseandglobalFolder: .yarn/global— despiteenableGlobalCachebeing disabled, Yarn still writes to the global folder, so it is redirected into the project to stay within the permitted write scope.lavamoat/is excluded from ESLint and oxfmt — the plugin sources are vendored from upstream and are intentionally kept unmodified so they remain easy to diff against the template.References
Based on MetaMask/metamask-module-template#335
Checklist