Skip to main content
ZeroPath’s SCA analyzers recognize the following ecosystems out of the box:

npm / Yarn / pnpm

PyPI

Go modules

Maven / Gradle / SBT

https://mintcdn.com/zeropath/3LQWG-DWQmf_zR2q/icons/csharp.svg?fit=max&auto=format&n=3LQWG-DWQmf_zR2q&q=85&s=a369b07fdfa85a098eef35c035d7c098

NuGet

https://mintcdn.com/zeropath/3LQWG-DWQmf_zR2q/icons/ruby.svg?fit=max&auto=format&n=3LQWG-DWQmf_zR2q&q=85&s=e98ed481966bcbb1508f8d69e680b60e

RubyGems

crates.io (Cargo)

Packagist / Composer

https://mintcdn.com/zeropath/3LQWG-DWQmf_zR2q/icons/elixir.svg?fit=max&auto=format&n=3LQWG-DWQmf_zR2q&q=85&s=1561f8905cfcc6ab231dbcb15aaf5db3

Hex (Elixir)

https://mintcdn.com/zeropath/3LQWG-DWQmf_zR2q/icons/dart.svg?fit=max&auto=format&n=3LQWG-DWQmf_zR2q&q=85&s=c3fa2a0a3350a59c4f7fcd10cbeff84b

Pub (Dart/Flutter)

Swift

Haskell (Hackage)

R (CRAN)

Every dependency record tracks whether ZeroPath saw it declared directly or pulled in transitively, so you can apply different policies to first-party choices and vendor libraries. Development and optional dependencies declared in your manifests are inventoried too; reachability helps separate runtime-relevant findings from dev-only noise.

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

EcosystemWithout a committed lockfile
npm / Yarn / pnpmFull 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 modulesDirect 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
RubyDirect deps only — commit Gemfile.lock
PHPDirect deps only — commit composer.lock
ElixirDirect deps only — commit mix.lock
Dart / FlutterDirect deps only — commit pubspec.lock
SwiftDirect deps only — commit Package.resolved
For every ecosystem marked Direct deps only, a missing lockfile means transitive dependencies aren’t resolved and range specifiers stay ambiguous, so transitive vulnerability matching and SBOM completeness suffer. ZeroPath still records your direct dependencies and flags the manifest with a Transitive dependencies unresolved warning so the gap is visible. See Coverage & warnings for how to clear it, including the commands to generate each lockfile.
For npm/Yarn/pnpm, Maven, and a fully ==-pinned requirements.txt, a committed lockfile is optional — it only makes scans faster and more deterministic.

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

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.
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.
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.
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).
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.
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.
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 (both dependencies and optional-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.