Skip to content

chore: harden Yarn install scripts in the JS SDK - #1019

Merged
kylemcd merged 1 commit into
mainfrom
kyle-kno-13806-harden-yarn-install-scripts-in-the-js-sdk-disable-by-default
Jun 17, 2026
Merged

chore: harden Yarn install scripts in the JS SDK#1019
kylemcd merged 1 commit into
mainfrom
kyle-kno-13806-harden-yarn-install-scripts-in-the-js-sdk-disable-by-default

Conversation

@kylemcd

@kylemcdkylemcd commented Jun 17, 2026

Copy link
Copy Markdown
Member

Description

Hardens Yarn install-script execution in the monorepo to reduce supply-chain attack surface. Closes KNO-13806.

Why. Install/postinstall scripts are the primary execution vector for the recent wave of npm supply-chain attacks — Shai-Hulud and the nx, chalk, and debug compromises all ran their payloads through a postinstall script. The root .yarnrc.yml had no script hardening, so any installed package could run arbitrary code at install time, in CI and on contributor machines. As a published SDK, a compromised install step here would also flow out to every downstream consumer.

What & how.

  • .yarnrc.ymlenableScripts: false: deny all dependency build scripts by default.
  • package.json → a dependenciesMeta allow-list re-enables (built: true) only the packages that genuinely need to compile or download a binary at install time:
    • @swc/core, esbuild — build toolchain (required for build:packages)
    • sharp — native image processing (Next.js examples)
    • unrs-resolver — native module resolver behind eslint-import-resolver-typescript (required for lint)

dependenciesMeta lives in the manifest, not.yarnrc.yml — Yarn 4.9.1 does not recognize it as a yarnrc setting (verified via yarn config + the docs). The lockfile change is just Yarn recording that allow-list against the root workspace.

Re-derived the allow-list from a fresh install rather than trusting the proposed list. A clean install surfaced one extra package with an install script: msgpackr-extract (pulled in transitively by @expo/metro-config). It's left denied — it's example/dev tooling only, ships its native binary via a prebuilt-binary optional dependency (@msgpackr-extract/msgpackr-extract-*), and falls back to pure JS, so its postinstall doesn't need to run. That's the more-hardened choice and is explicitly sanctioned by the ticket ("only needed by examples or tooling … can stay denied").

Verification — Yarn 4.9.1, all green locally:

  • Confirmed the open question from the ticket: built: true acts as an allow-list override of a global enableScripts: false (re-enables only the listed packages), not purely a deny-list.
  • Fresh yarn install and yarn install --immutable (what CI runs): exactly the 4 allow-listed packages build; msgpackr-extract is denied with a warning (YN0004), not an error; no install errors; yarn.lock stays consistent under --immutable.
  • Workspace lifecycle scripts are unaffected — the root postinstall: manypkg check still runs.
  • yarn format:check, yarn build:packages, yarn type:check, yarn lint, and yarn test (74 files / 878 tests) all pass.

Checklist

  • No tests added — config-only change to monorepo install tooling; no published package code changes (and therefore no changeset).

@linear-code

Copy link
Copy Markdown

KNO-13806

@vercel

vercelBot commented Jun 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
javascript-ms-teams-connect-exampleReadyReadyPreview, CommentJun 17, 2026 1:45pm
javascript-nextjs-exampleReadyReadyPreview, CommentJun 17, 2026 1:45pm
javascript-slack-connect-exampleReadyReadyPreview, CommentJun 17, 2026 1:45pm
javascript-slack-kit-exampleReadyReadyPreview, CommentJun 17, 2026 1:45pm

Request Review

@changeset-bot

changeset-botBot commented Jun 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: cf44b3d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Install and postinstall scripts are the primary execution vector for the
recent wave of npm supply-chain attacks (Shai-Hulud, nx, chalk, debug).
The root .yarnrc.yml had no script hardening, so any installed package
could run arbitrary code at install time in CI and on contributor
machines. As a published SDK, a compromised install step would also flow
out to downstream consumers.
Disable build scripts globally (enableScripts: false) and allow-list only
the packages that genuinely need to compile or download a binary at
install time, via dependenciesMeta.<pkg>.built: true in the root
package.json (Yarn 4 does not recognize dependenciesMeta in .yarnrc.yml):
- @swc/core, esbuild — build toolchain (required)
- sharp — native image processing (Next.js examples)
- unrs-resolver — native resolver (eslint-import-resolver-typescript)
msgpackr-extract (pulled in by @expo/metro-config) is left denied: it is
example/dev tooling only, ships a prebuilt-binary optional dependency, and
falls back to pure JS, so it does not need its install script to run.
Verified on Yarn 4.9.1 that built: true re-enables only the listed
packages under a global enableScripts: false (allow-list, not deny-list).
Fresh install, immutable install, build:packages, type:check, lint, and
the full test suite (878 tests) all pass; workspace lifecycle scripts
(root postinstall: manypkg check) are unaffected.
@codecov

codecovBot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.55%. Comparing base (24a8bb2) to head (cf44b3d).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@ Coverage Diff @@## main #1019 +/- ##
=======================================
Coverage 63.55% 63.55% =======================================
Files 208 208 Lines 9924 9924 Branches 1280 1280 =======================================
Hits 6307 6307 Misses 3592 3592 Partials 25 25 

@kylemcd
kylemcd merged commit 2ea1a6a into mainJun 17, 2026
12 checks passed
@kylemcd
kylemcd deleted the kyle-kno-13806-harden-yarn-install-scripts-in-the-js-sdk-disable-by-default branch June 17, 2026 14:26
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@kylemcd@meryldakin