MobDev.SecurityScan.OsvScanner (mob_dev v0.5.1)

Copy Markdown View Source

Wrapper around the osv-scanner CLI (https://google.github.io/osv-scanner/).

osv-scanner queries the OSV.dev database, which aggregates advisories from many ecosystems (Hex, Maven/Gradle, Swift PM, npm, PyPI, RubyGems, ...) into a single feed. Several Mob scan layers (hex_deps, gradle_deps, swift_deps) call this helper so the binary integration lives in one place.

All public functions are pure orchestration — no parsing logic, no finding shape. Parser does the actual JSON → Finding translation, which keeps the network/process side easy to mock and the parser trivially testable with fixture JSON.

Summary

Types

What to scan. {:lockfile, path} for a single lockfile, {:directory, path} for a recursive scan that finds every supported manifest under the tree.

Functions

True if osv-scanner is on PATH.

Scan a target and return findings tagged with the given layer.

Types

target()

@type target() :: {:lockfile, Path.t()} | {:directory, Path.t()}

What to scan. {:lockfile, path} for a single lockfile, {:directory, path} for a recursive scan that finds every supported manifest under the tree.

Functions

installed?()

@spec installed?() :: boolean()

True if osv-scanner is on PATH.

scan(target, layer, opts \\ [])

@spec scan(target(), atom(), keyword()) ::
  {:ok, [MobDev.SecurityScan.Finding.t()]}
  | {:error,
     :not_installed | {:not_found, Path.t()} | {:scan_failed, String.t()}}

Scan a target and return findings tagged with the given layer.

Returns:

  • {:ok, findings} — scan completed (findings list may be empty)
  • {:error, :not_installed} — binary not on PATH
  • {:error, {:not_found, path}} — target path doesn't exist
  • {:error, {:scan_failed, reason}} — binary exited non-zero or produced unparseable output

osv-scanner exits with code 1 when findings are present and 0 when clean — this function treats both as success and only signals :scan_failed for true errors (code 127, malformed JSON, etc.).