yarnpkg / yarnpkg/berry

[Feature] Allow vendor to control dependency versions

Open
#3,968 3 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
8.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

  • I'd be willing to implement this feature (contributing guide)
  • This feature is important to have in this repository; a contrib plugin wouldn't do

Describe the user story

We are the vendors of a CLI tool that touches people's AWS infrastructure. Since the tool will by design be run in situations where it has a lot of access to our user's AWS accounts, there are some concerns around this tool being a target for supply chain attacks.

The NPM ecosystem commonly has incidents like these, and it's only a matter of time before it happens to us:

We'd therefore like to have tight control of our tool's dependencies. Preferably, we want to ensure that when a user installs our tool, they get a "known good" version of the tool and all of its dependencies. However, that requires that we can control the point versions of every dependency in our dependency closure.

Yes, we can control the version strings we use to depend on our dependencies: we can avoid using ^ or ~ or >= in our package.json. But we cannot control the package.jsons used by our dependencies, and their dependencies, and it's an unfortunate truth that nearly everyone uses ^ everywhere, which means any dependency in our closure is potentially an attack vector.

You can say yarn.lock solves this issue, but it doesn't really. yarn.lock only applies to existing projects. It doesn't apply to new projects, nor does it apply to global installations. Tomorrow, the owner of any package in our dependency closure can release a minor point upgrade with malicious code in it and every users that initializes a new project or uses yarn to install the CLI globally after that is immediately affected.

I would also add that relying on yarn.lock to solve this issue punts it from someone with a lot of information (the person who wrote and vends the CLI) to someone with very little information (the consumer of the CLI, who should be able to treat the abstraction provided as a black box and shouldn't need to know about the transitive dependency tree hidden behind it). Case in point: it doesn't seem right that we have to rely on 1000s of our users having the knowledge that colors 4.1.2 became unusable and they should all revert their dependency to 4.1.0 and take care not to upgrade it again in the future... especially given that the alternative is—or at least, should be—that we fix this automatically for them.

To mitigate this problem for our users, we need to be able to control the dependency closure that our CLI tool runs against.

For users using NPM, we can do this today (using the npm-shrinkwrap.json mechanism), but we have no mechanism to protect our Yarn users in the same way. And I really don't know what to tell them, except to stop using Yarn which I'd rather not do.

Describe the solution you'd like

I have seen one some website that it is impossible for you to consume the npm-shrinkwrap.json file directly. I'm not asking for that. I'm asking for a comparable mechanism. It's fine if it requires a new file with other data in it. If the mechanism exists, we can invest time to produce an appropriate configuration file.

We just need a way for a package vendor to control versions in a subsection of the dependency tree, in whatever way possible.

We need every user of Yarn out there to be protected out of the gate, in every situation where they might install this tool, so this cannot go into a plugin.

Describe the drawbacks of your solution

I imagine it might be hard to define how this interacts with the yarn.lock of the environment into which packages are being installed, or how it interacts with resolutions. To a first approximation, that might be resolved by saying that a yarn-shrinkwrap.lock (or whatever) file needs to be complete, and no dependencies may be requested in that subtree that are not covered by the shrinkwrap file. Let's say you initially don't support resolutions overrides either.

I suppose the feature might also be abused by people who don't understand its purpose, might reduce chances of package deduplication, and might complicate the implementation of PnP in ways I don't completely oversee.

I'm still not sure any of the "it will be hard" arguments are reasons not to do it, given what's at stake.

Describe alternatives you've considered

If worse comes to worst, I suppose we can always choose to vendor-in all our dependencies, bloating our module size and potentially creating a bit of licensing/copyright hassle we'll have to sort through. Other than that, I really can't think of other alternatives.

I would hate to have to do that though, which is why I'm here asking for you to reconsider first.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no files, tests, or entry points. Start by reviewing the contributing guide and Yarn's existing lockfile, dependency-resolution, and resolutions behavior; define how a vendor-controlled dependency subtree would interact with each, then document tests for installation, global packages, and new projects as the completion criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
devtools, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.