Automated Threat Modeling

Build-less Dependency Scanning: SCA Coverage You Can Actually Verify

SCA forces a bad trade: run a fragile build for full coverage, or scan manifests and miss the transitive majority. ZeroPath resolves the full graph build-lessly for npm, Maven, and pinned Python, and reports exactly how much of your supply chain each scan resolved.

Product

5 min read

Gaurav Sarraf
Gaurav Sarraf

2026-08-03

Build-less Dependency Scanning: SCA Coverage You Can Actually Verify

Introduction

Ask a security engineer, a platform team, or a CISO where software composition analysis (SCA) lets them down, and you hear one of two complaints. Either the tool needs a full build to see the whole dependency tree, so it breaks on the repositories that matter most, or it reads what it can, prints a short list of CVEs, and stays quiet about the parts of your supply chain it never resolved. The first is fragile. The second is worse, because a blind spot presented as a clean scan is a risk you can't see, let alone manage.

ZeroPath's SCA engine takes a different route. It resolves your dependency graph without a build wherever it can, and it reports how much of your supply chain each scan resolved, broken down by ecosystem and by repository. This post explains how build-less resolution works and why coverage is the number to watch.

Why do SCA tools miss most of your dependency risk?

Most of your open-source risk doesn't live in the packages you picked. It lives in the transitive ones: the dependencies of your dependencies, several layers deep, that nobody ever typed into a manifest. A scanner that only reads package.json or pom.xml sees your direct dependencies and stops there, so it misses the majority of the graph, the part where vulnerabilities tend to hide.

The usual fix is to run a build and scan whatever the package manager resolves. It works, but it's expensive and brittle: you need the right toolchain, private-registry access, and patience for cold caches, and you're now running project-controlled build logic on your scanning infrastructure. Teams that can't get the build green fall back to manifest-only scanning and inherit the blind spot anyway. Either way, most tools never tell you how much of the tree they saw.

What does "build-less" dependency resolution mean?

Build-less means ZeroPath resolves your full transitive dependency graph straight from your manifests, with no build step and no container. It works through a deterministic ladder that always prefers the most trustworthy source available:

  • If you committed a lockfile, ZeroPath parses it exactly as written. A committed lockfile is the version set you actually ship, so we read it rather than re-resolve it.

  • If there's no lockfile, ZeroPath runs the package manager's own resolver inside a locked-down sandbox with lifecycle scripts disabled. That's the resolution step only, with no build and no arbitrary code execution. For npm, Yarn, pnpm, and Maven, this produces the complete transitive tree.

  • Where a graph genuinely can't be resolved without running the project, ZeroPath falls back to registry metadata or resolves your direct dependencies only, and says so instead of guessing.

For npm, Maven, and a fully pinned requirements.txt, you get full transitive coverage with no lockfile and no build at all. Because resolution still touches attacker-influenced input, ZeroPath runs it inside a per-scan gVisor sandbox with egress locked to a short allowlist, so resolving your dependencies can't become a foothold in your pipeline.

Why parse the lockfile instead of re-resolving it?

It sounds like a detail, but it separates scanning what you ship from scanning something else. When a scanner re-resolves your committed lockfile, it drifts your dependencies forward to whatever resolves today, often a newer, patched version. The scan looks clean while the vulnerable versions you deploy sit untouched in your lockfile. ZeroPath treats the lockfile as ground truth and reports the versions you really run.

Coverage you can verify

Most tools won't show you their own coverage. Every ZeroPath scan records, for each ecosystem in each repository, how many dependency manifests it discovered versus how many it fully resolved. That ratio is your real coverage, on the dashboard as a measurement, not a number the tool inferred or rounded up. A repository that was never measured shows up as "not measured," never as 100 percent.

Each manifest also carries a resolution fidelity: deterministic (resolved from your lockfile), build-less (the full graph from your manifest), or degraded, direct dependencies only (a lockfile is missing, so only your direct deps resolved). When something is incomplete, ZeroPath raises a specific, typed warning, such as Missing lockfile, Transitive dependencies unresolved, or Dependency resolution failed, each with the exact command to fix it, like go mod tidy or ./gradlew dependencies --write-locks. Filter the warnings, export them to CSV, or pull the whole picture through the API. A blind spot shows up as a blind spot you can assign and close, instead of as silence.

What happens when a scan can't resolve something?

It carries your findings forward. If a manifest fails to resolve, from a network blip or an unreachable parent POM, ZeroPath keeps the existing findings rather than marking them resolved. A finding is auto-closed only when a successful scan confirms the vulnerable version is gone. A flaky scan can't turn a vulnerable repository green.

ZeroPath also refuses to guess. If a version can't be determined, from an unresolved range or a broken parent chain, the package still goes into your inventory and SBOM but isn't matched against advisories, because a guessed version is a false positive waiting to happen. You get alerted on the versions you actually ship, and nothing else.

Key takeaways

  • Transitive dependencies are where most open-source risk lives. Manifest-only scanning misses them, and build-required scanning is fragile and slow.

  • ZeroPath resolves the full transitive graph without a build or a lockfile for npm, Maven, and fully pinned Python, using each manager's own resolver with scripts off, in a sandbox.

  • Committed lockfiles are parsed, never re-resolved, so you scan the versions you ship rather than whatever resolves today.

  • Every scan reports discovered versus resolved manifests per ecosystem and repository, with typed warnings and fix commands.

  • Failed resolutions carry findings forward and never guess a version, so a broken scan can't hide a real vulnerability.

See it on your own code

Run a scan and open the Supply Chain view to see your resolution coverage across every ecosystem and repository, blind spots included. Get a demo of ZeroPath.

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Jira
  • Linear
  • Slack
  • Security Compass
Security magnifying glass visualization