Skip to content

Dependency scanning

The agent walks several standard project locations every 6h and parses lockfiles per package manager. Only (name, version, ecosystem, is_direct) tuples + the project_path are sent to the hub — no file contents, no env vars, no secrets.

Scanned paths

/var/www
/opt
/srv
/home/<user>
/root
/var/lib/jenkins/workspace
C:\inetpub\wwwroot (Windows)
C:\Program Files\nodejs (Windows)

Depth: max 6 levels. Skips node_modules, vendor, .git, .svn, .idea, .vscode, target, build, dist, __pycache__, and anything starting with ..

Recognised lockfiles

FileEcosystem
package-lock.json (npm v1/v2/v3)npm
yarn.locknpm
pnpm-lock.yamlnpm
requirements.txtPyPI
Pipfile.lockPyPI
composer.lockPackagist
Gemfile.lockRubyGems
go.sumGo

Not (yet) supported: Cargo.lock, pubspec.lock, mix.lock, Maven pom.xml. PRs welcome.

Caps to bound payload

  • Max 100 projects per host
  • Max 20,000 packages total per host
  • node_modules-style transitives are included but marked is_direct=false

What the hub does

The DependencyScanWorker picks up every 30s (cold-start) or 6h (steady) every unique (ecosystem, package_name, version) tuple from inventory_dependencies and batch-queries https://api.osv.dev/v1/querybatch (1000 tuples per call). For each match it fetches the vuln detail from /v1/vulns/<id>, normalises severity, and writes to inventory_dependency_cves.

Endpoint: GET /api/v1/agents/:id/inventory/dependencies → returns:

{
"projects": [
{ "project_path": "/var/www/api", "manifest": "package-lock.json",
"ecosystem": "npm", "dep_count": 1248, "direct_count": 47,
"cve_count": 89, "critical_count": 3 }
],
"cves": [
{ "vulnerability_id": "GHSA-9jj7-4m8r-rfcm",
"severity": "CRITICAL", "package_name": "jackc/pgx/v5",
"installed_version": "5.7.0", "fixed_version": "5.9.0", ... }
]
}

Privacy

What DOES go to the hub:

  • Project path (e.g. /var/www/api)
  • Package name + version
  • Ecosystem label
  • Direct/transitive flag

What does NOT go to the hub:

  • Lockfile contents
  • Other files in the project (no .env, no source code)
  • Sha256 of the lockfile itself
  • Env vars from the project

The npm ls output on the host itself reveals the exact same information to anyone with shell access. We send no more than that.

What to do with findings

inventory_dependency_cves rows are idle data without operator action. You can:

  1. Browse them in /agents/<id>Dependencies tab (per agent, per project)
  2. Fleet-wide search in /inventory (filter on CVE id, package, severity)
  3. Create an alert rule: trigger when an agent with tag production has ≥1 CRITICAL dependency CVE (combinable with threshold + duration)
  4. CSV export for your security team

Limitations to know:

  • No typosquatting detection (react-dom vs react.dom). OSV.dev matches only on exact (package, version).
  • No malicious install-script detection (post-install hooks that drop backdoors).
  • No detection of compromised maintainer accounts where legitimate versions suddenly become malicious.

For those three you’d add tools like Socket.dev or npm audit signatures (sigstore) — on the roadmap.