Skip to content

fix(nodejs): prune yarn workspace dev-dependency leak in workspace scans#6888

Open
andreipopa-who wants to merge 1 commit into
mainfrom
fix/yarn-workspace-dev-dep-leak
Open

fix(nodejs): prune yarn workspace dev-dependency leak in workspace scans#6888
andreipopa-who wants to merge 1 commit into
mainfrom
fix/yarn-workspace-dev-dep-leak

Conversation

@andreipopa-who

Copy link
Copy Markdown

Pull Request Submission Checklist

  • Follows CONTRIBUTING guidelines
  • Commit messages are release-note ready, emphasizing what was changed, not how.
  • Includes detailed description of changes
  • Contains risk assessment (Low | Medium | High)
  • Highlights breaking API changes (if applicable)
  • Links to automated tests covering new functionality
  • Includes manual testing instructions (if necessary)
  • Updates relevant GitBook documentation (PR link: ___)
  • Includes product update to be announced in the next stable release notes

What does this PR do?

Fixes false positives in Yarn Berry (v2/3/4) workspace scans: the dev-only build tooling (webpack, babel, ...) of a workspace package was being reported as production dependencies of any sibling package that consumed it.

Yarn Berry flattens a workspace member's dependencies + devDependencies into a single dependencies block in yarn.lock with no dev marker. When a member is consumed as a prod dependency, the parser walked that whole block and inherited the parent's prod scope, so the consumed member's dev tooling (and its transitive tree) was promoted into the production graph.

processYarnWorkspaces now collects each workspace member's package.json dependency groups (from the already-discovered target files) and passes them to the lockfile parser via YarnLockV2WorkspaceArgs.workspacePackages, so the parser can prune the dev-only dependencies of a consumed workspace package.

Depends on snyk-nodejs-lockfile-parser exposing YarnLockV2WorkspaceArgs.workspacePackages (snyk/nodejs-lockfile-parser#311). The snyk-nodejs-lockfile-parser dependency must be bumped to the released version for the prune to take effect; the change is backward-compatible until then.

Before / after

Scanning apps/my-app (whose only prod dep is the workspace package @demo/shared-lib, which has only devDependencies):

prod deps in my-app graph dev tooling present
before 242 webpack, webpack-cli, @babel/core, @babel/preset-env, babel-loader
after 1 (@demo/shared-lib) none

Where should the reviewer start?

src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts — the new collectYarnWorkspacePackages helper, the pre-pass that gathers member manifests before the main loop (a consumer may be processed before the member it depends on), and the workspacePackages argument added to the parseYarnLockV2Project call.

How should this be manually tested?

npx jest test/jest/unit/lib/plugins/yarn-workspaces-parser.spec.ts

The processYarnWorkspaces - dev-dependency leak suite scans test/fixtures/yarn-workspace-dev-deps and asserts the consumed member's dev tooling is absent by default and present under --dev. (Requires a snyk-nodejs-lockfile-parser build that includes workspacePackages.)

What's the product update that needs to be communicated to CLI users?

Yarn Berry workspace scans no longer report a consumed workspace package's dev-only dependencies as production. Existing workspace results will show fewer (correctly scoped) production dependencies.

Risk assessment (Low | Medium | High)?

Low. Behavior is gated on the new workspacePackages map; with no map (or no parser support) behavior is unchanged. Non-workspace scans are unaffected. It is a dep-graph-shape change for Yarn workspaces (fewer prod deps), so worth a release note.

What are the relevant tickets?

When a Yarn Berry workspace package is consumed as a production dependency, its
dev-only tooling (webpack, babel, ...) was reported as production dependencies of
the consumer, because yarn.lock merges a workspace member's dependencies and
devDependencies into one block with no dev marker.

Populate the lockfile parser's `workspacePackages` map (member name -> dep
groups) in processYarnWorkspaces so it can prune the dev-only deps of a consumed
workspace package. The member manifests are collected up front from the
already-discovered target files (a consumer may be processed before the member it
depends on).

Requires snyk-nodejs-lockfile-parser with
`YarnLockV2WorkspaceArgs.workspacePackages` (bump the dependency once released).
@andreipopa-who andreipopa-who requested a review from a team as a code owner June 9, 2026 07:20
@snyk-io

snyk-io Bot commented Jun 9, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@snyk-pr-review-bot

Copy link
Copy Markdown

PR Reviewer Guide 🔍

🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Partial Pre-collection 🟡 [minor]

The pre-collection loop for workspaceManifestContents uses a try-catch block that silently logs errors. If a package.json fails to read (e.g., due to permissions) for a workspace member, that member's dependency groups will be missing from workspacePackages. Consequently, when the lockfile parser processes a consumer of that member, it will lack the metadata needed to prune dev-dependencies, leading back to the original 'leak' behavior for that specific package.

try {
  workspaceManifestContents.push(
    getFileContents(root, pathUtil.join(directory, 'package.json')).content,
  );
} catch (e) {
  debug(`Could not read package.json in ${directory}: ${e}`);
}
📚 Repository Context Analyzed

This review considered 8 relevant code sections from 6 files (average relevance: 0.93)

🤖 Repository instructions applied (from AGENTS.md)

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️

Since the CLI is unifying on a standard and improved tooling, we're starting to migrate old-style imports and exports to ES6 ones.
A file you've modified is using either module.exports or require(). If you can, please update them to ES6 import syntax and export syntax.
Files found:

  • src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts

Generated by 🚫 dangerJS against 2d4e58d

Sign up for free to 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.

1 participant