npm / Yarn / pnpm
PyPI
Go modules
Maven / Gradle / SBT
NuGet
RubyGems
crates.io (Cargo)
Packagist / Composer
Hex (Elixir)
Pub (Dart/Flutter)
Swift
Haskell (Hackage)
R (CRAN)
How resolution works
ZeroPath resolves your dependency graph directly from your manifests wherever it can, with no build step or container required, and falls back to your committed lockfile everywhere else. The practical contract is per-ecosystem, summarized in the table below. Two rules hold everywhere:- Direct dependencies are scanned even when the transitive graph can’t be built. ZeroPath records and vulnerability-matches the packages you declared directly, so a missing lockfile costs you transitive depth, not your direct findings.
- Unknown versions aren’t guessed. If a version can’t be determined, for example an unresolved range or a broken parent chain, the package is still recorded in your inventory and SBOM but is not vulnerability-matched. This avoids false positives from guessed versions.
Coverage without a committed lockfile
| Ecosystem | Without a committed lockfile |
|---|---|
| npm / Yarn / pnpm | Full transitive coverage — resolved directly from package.json |
Maven (pom.xml) | Full transitive coverage — resolved deterministically from your POMs (parent, BOM, and properties); no lockfile required |
Python (requirements.txt, fully ==-pinned) | Resolved as-is — every pinned package is scanned (a pip freeze / pip-compile file already lists transitives) |
Python (pyproject.toml, Pipfile, partially-pinned requirements.txt) | Direct deps only — manage via pyproject.toml/Pipfile and commit poetry.lock, uv.lock, or Pipfile.lock (or fully ==-pin) |
| Go modules | Direct deps only — commit go.sum (go mod tidy) |
Gradle (build.gradle, .kts) | Direct deps only — commit gradle.lockfile |
SBT (build.sbt) | Direct deps only — commit build.sbt.lock or lock.sbt |
Cargo (Cargo.toml) | Direct deps only — commit Cargo.lock |
NuGet (*.csproj, *.fsproj, *.vbproj) | Direct deps only — commit packages.lock.json |
| Ruby | Direct deps only — commit Gemfile.lock |
| PHP | Direct deps only — commit composer.lock |
| Elixir | Direct deps only — commit mix.lock |
| Dart / Flutter | Direct deps only — commit pubspec.lock |
| Swift | Direct deps only — commit Package.resolved |
Compiled & vendored artifacts
Binary JVM artifacts committed to your repository, such as JARs and WARs, are scanned for the packages embedded inside them. Those packages appear in your inventory alongside source-declared dependencies, with a Compiled source-type badge (e.g. JAR, WAR), so you can see vendored or pre-built libraries that manifest-only analysis would miss. The Dependencies inventory lets you filter by Source Type to isolate compiled vs. source-declared findings.Ecosystem notes
Go modules
Go modules
ZeroPath handles the
+incompatible suffix used by pre-module Go packages
(major version 2+), matching versions like v3.2.0+incompatible to known
advisories. Go pseudo-versions (e.g. v0.0.0-20231215084216-abcdef123456) are
commit snapshots, not published releases, so ZeroPath records them in inventory
but doesn’t attempt advisory version-matching on them.Maven
Maven
Multi-module (reactor) builds are fully resolved: ZeroPath indexes every POM
in the repository and resolves
<parent> references across modules even when
<relativePath/> is empty or absent, so a child can inherit
<dependencyManagement> versions from a sibling’s parent. Parent POMs that
declare dependencies only in <dependencyManagement> are captured, and
classifier-bearing artifacts are attributed to the correct package. When a
parent POM can’t be resolved locally or remotely, versions inherited through
that chain are treated as unresolved rather than guessed.Gradle
Gradle
Beyond plain
build.gradle(.kts) declarations, ZeroPath also recognizes
dependencies declared through version catalogs (libs.versions.toml),
convention plugins, platform/BOM constraints, and the Kotlin DSL. Commit
gradle.lockfile (./gradlew dependencies --write-locks) for the full
transitive tree.SBT (Scala)
SBT (Scala)
ZeroPath records direct dependencies from
build.sbt, and parses a committed
lockfile for the full transitive tree: build.sbt.lock
(sbt-dependency-lock) or
lock.sbt (sbt-lock).NuGet
NuGet
Package ids are matched case-insensitively, so casing differences between a
manifest and the registry never cause a miss. Opt into NuGet lockfile mode and
commit
packages.lock.json (dotnet restore --use-lock-file --force-evaluate,
NuGet 4.9+) for transitive coverage.Cargo (Rust)
Cargo (Rust)
Binary crates commit
Cargo.lock by default, and ZeroPath uses it directly.
Library crates commonly omit it (per Cargo’s guidance); commit
Cargo.lock (cargo generate-lockfile) for transitive coverage. A crate that
resolves to multiple versions in the same graph is reported as separate
(name, version) pairs, so each one reaches advisory matching.Python manifest formats
Python manifest formats
All common formats are supported:
- requirements.txt — standard pip format
- Pipfile — Pipenv (
[packages]/[dev-packages]) - pyproject.toml (Poetry) — including 1.2+ group dependencies
- pyproject.toml (PEP 621) — the
[project]table used by uv, hatch, flit, setuptools, and pdm (bothdependenciesandoptional-dependencies)
Every finding records a package’s place in the graph (direct or transitive) and
the chain that introduced it, and links back to the exact manifest file and line
where the dependency was declared rather than the lockfile. A package reached
through multiple dependency paths is deduplicated into a single inventory entry,
so counts reflect unique packages. See Blast radius for how
the dependency chain becomes call-site impact during an upgrade.