With Yarn Plug'n'Play a project has no node_modules folder, so a scanner that walks that folder may find nothing. Use a tool that reads the lockfile, then check the component count against your expectations. If the count is zero or tiny, the tool is looking in the wrong place.
What PnP changes
The Yarn documentation says Plug'n'Play is the default installation strategy in modern releases of Yarn. A PnP project lacks a node_modules folder. Yarn generates a single Node.js loader file, named .pnp.cjs, that holds the dependency tree so tools can find packages on disk. It references packages directly through their cache path instead of copying them into the project. The docs add that PnP can be replaced with node_modules or pnpm style symlinks.
So the shape of the filesystem is different from what many scanners expect.
Which input should an SBOM tool use?
| Input | Available under PnP? | Notes |
|---|---|---|
| node_modules folder | No, by default | Scanner finds nothing |
| yarn.lock | Yes | Records resolved packages |
| package.json | Yes | Declared ranges, not resolved |
| .pnp.cjs | Yes | Dependency tree as Yarn resolved it |
Lockfile based detection is the usual answer. Microsoft's open source component detection project, for example, lists NPM support as including Yarn and pnpm, though its page does not describe per detector details, so test your own tool and do not assume.
A five step test
- Count the packages in the lockfile. Look at the number of resolved entries.
- Generate the SBOM.
- Count components, excluding the root.
- Compare. They should be close, with differences you can explain, such as one lockfile entry serving several ranges.
- Spot check three transitive packages by name.
If you see zero components, the tool probably walked the folder. Switch its mode or its input, or change the Yarn linker to node_modules for the scan job.
The linker option
Changing the linker for CI just is a fair workaround. It means installing in a scan job with the node_modules strategy so folder based tools see packages. The tradeoff is that the scanned tree is not the one you deploy, so your SBOM describes a close cousin. Prefer lockfile input if the tool supports it.
Pitfalls
Yarn classic and modern Yarn write differently formatted lockfiles, so a tool must support the one you use. Resolutions and patches can change what is actually installed. Check that those show up. And treat dev dependencies carefully: decide whether the file is for production or for review.
A worked example
A team migrates a service from a node_modules based install to Plug'n'Play. Before the move, their SBOM job walked the node_modules folder and reported about 800 components. After the move, the same job reports 3. The numbers are illustrative. Nothing about the application's dependencies changed, but the filesystem layout did.
The investigation goes like this:
- Check that the lockfile still exists and still lists the packages. It does.
- Look at the project directory. There is no node_modules folder, and a .pnp.cjs file sits in its place, as the Yarn documentation describes.
- Read the SBOM tool's docs. It scans installed folders by default.
- Switch the tool to lockfile input, or point it at the lockfile explicitly.
- Rerun. The count returns to roughly the same number as before.
The lesson is that a drop in count after a tooling change is a signal, not a success.
What each input tells you
| Input | Strength | Weakness |
|---|---|---|
| Lockfile | Exact resolved versions, works without install | Does not show what is on disk |
| Package manifest | Declared intent | Ranges, not resolved versions |
| Loader file | What Yarn resolved for Node | Not a standard SBOM format |
| Installed folder | What a classic install put on disk | Absent under PnP |
Lockfile input is the practical choice. It works in CI without a full install and gives resolved versions.
The node_modules linker as a fallback
The Yarn docs say PnP can be replaced by node_modules or pnpm style symlinks. If a scanning tool cannot read the lockfile, you can run the scan job with a node_modules install. Be aware that the scanned tree then differs from what you deploy, so note this in the SBOM metadata.
Checks to build into the job
- Compare the SBOM component count with the number of resolved entries in the lockfile, with a tolerance you can explain.
- Fail the job if the count is below a floor taken from the last release.
- Spot check that a few well known transitive packages are present.
- Verify that dev dependencies are marked or excluded as you intend.
- Record the Yarn version and the linker mode in the file's metadata.
Patches and resolutions
Modern Yarn lets a project patch packages and force versions of transitive dependencies. Those changes affect what runs. Check that your SBOM reflects the patched or forced version, and note the patch. If the tool reads solely the manifest, it may show the original range.
Zero installs
Some teams commit the package cache to the repository. If yours does, the repository itself contains the dependency archives. That is convenient for reproducibility, but it also means large diffs on updates and a need to review changes to binary archives. Your SBOM review should include the lockfile diff as the readable summary of what changed.
Communicating limits
If you ship an SBOM generated from the lockfile, say so in the cover note. Readers who expect an installed tree should know the file describes resolved versions, not a scan of disk.
Where Safeguard fits
Safeguard scans dependencies and SBOMs. To see how your lockfile reads, try the free scan at gold.safeguard.sh/scan on a PnP project and compare the count.
Try it yourself
Click through it at your own pace, or open it full screen.
Click into a few components and note how direct and transitive packages are separated.
Quick check
Why does my scan of a Yarn project show zero packages?
Under PnP there is no node_modules folder. The tool may be reading that folder. Use lockfile input.
Is .pnp.cjs an SBOM?
No. It is a loader holding the resolved tree for Node, not a bill of materials in a standard format.
Do I need to switch away from PnP to get an SBOM?
No. Use a tool that reads the lockfile. Switching the linker is a fallback for tools that cannot.
Sources
Last reviewed: 19 October 2026.