Skip to content

Getting Started

Package Probe scans your machine for software projects, discovers their dependencies (including transitive ones), validates where each package was installed from, and reports known vulnerabilities. This guide takes you from zero to your first fixed CVE.

There are two ways to use Package Probe:

  • The macOS app (Package Probe.app) — a GUI for day-to-day developer use.
  • The CLI (packageprobe, aliased pkgprb) — for terminals, scripts, and CI/CD.

Both are thin front ends over the same Rust engine, so a scan produces the same results either way.

Package Probe requires the one-time Base purchase (or an active 7-day trial) to run a fresh scan. Start a trial at any time with packageprobe trial <email> (GUI: the onboarding wizard’s License step). See Products & pricing for the base + pack model.

Terminal window
brew tap packageprobe/tap
# GUI app (macOS, Apple silicon only) — auto-updates via Sparkle
brew install --cask packageprobe
# CLI (macOS + Linux) — pre-built binary, no external runtime deps
brew install packageprobe/tap/packageprobe-cli

Pre-built artifacts are published on the GitHub Releases page:

  • macOS GUI — packageprobe-<version>.dmg (Apple silicon; macOS 14+ on an M-series Mac is required). Open the DMG and drag Package Probe.app to /Applications. It is code-signed and notarized; subsequent updates arrive automatically over Sparkle.

  • CLI — a per-platform tarball, each containing a single packageprobe binary at the root:

    PlatformArtifact
    macOS arm64packageprobe-cli-<version>-aarch64-apple-darwin.tar.gz
    Linux arm64packageprobe-cli-<version>-aarch64-unknown-linux-gnu.tar.gz
    Linux x86_64packageprobe-cli-<version>-x86_64-unknown-linux-gnu.tar.gz

    Intel Macs are not supported: packageprobe ships Apple silicon builds only.

    Terminal window
    tar xzf packageprobe-cli-<version>-<target>.tar.gz
    sudo mv packageprobe /usr/local/bin/
    packageprobe --version

    Each release also ships SHA-256 checksums — verify the download before installing.

Scan a repository in a pipeline with the dedicated packageprobe/scan-action:

- uses: packageprobe/scan-action@v1
with:
license-key: ${{ secrets.PACKAGEPROBE_LICENSE_KEY }}
vulns: true
policy: true
sbom-format: cyclonedx

The action auto-detects the runner (Linux/macOS, x86_64/arm64), verifies the CLI download checksum, and can diff vulnerabilities against the base branch and comment on the PR (comment-on-pr: true).

The Mac App Store and Setapp are additional macOS channels. When available they install the same app through the store’s own flow (no license-key step — the entitlement is provisioned by the store).

After installing, start a trial or activate a license.

Terminal window
packageprobe trial you@example.com # 7-day trial — all features unlocked
packageprobe login <license-key> # activate this machine with a purchased key

In the macOS app, the onboarding wizard (first launch) walks the same path: Welcome → License → Scan Paths → Languages → Done. The License step accepts a trial email or a license key, and the wizard is skippable if you want to explore first.

For CI/CD, skip machine activation entirely and validate statelessly by exporting your key — the CLI checks this before any on-disk license file:

Terminal window
export PACKAGEPROBE_LICENSE_KEY=pp_live_...

Configuration lives at ~/.packageprobe/config.yaml and is created automatically on first run. The two fields that matter for a first scan are paths (where to look) and languages (which ecosystems to enable):

scan_interval: manual # manual | 1h | 4h | 12h | daily
paths:
- /Users/you/Developer
languages:
- node
- python
- go

Use the key from the supported-ecosystem list for each language (node, python, rust, go, php, ruby, swift, dart, cocoapods, dotnet, java, elixir). In the macOS app the same settings are on the Settings screen (paths picker + a language toggle grid). Only the enabled languages are scanned — a narrowed languages list is surfaced explicitly in the output so a scoped scan is never mistaken for a clean whole-machine result.

Terminal window
# Fast scan — filesystem only, no network. Prints a JSON report to stdout.
packageprobe scan
# Scan + vulnerability enrichment (queries OSV via the vuln-proxy; slower first run).
packageprobe scan --vulns

The JSON report is a ScanEnvelope — a top-level object with fields like schema_version, scanned_at, and results (plus coverage/completeness fields described below). The results object holds one entry per discovered project, keyed by the project’s stable id; each entry carries its project_name, package_manager, resolved registries, and a dependencies list. With --vulns, each dependency gains a vulnerabilities array. Parse the results object, not the top-level keys. Write the report to a file with -o report.json. See the CLI reference for every subcommand, flag, and exit code.

Click Rescan in the toolbar (or wait for the configured scan_interval). A toast shows live progress; when it finishes, the sidebar lists every discovered project with a vulnerability shield colour-coded by its highest severity.

Select a project (or read its JSON block) and look at each dependency:

  • Severity — each vulnerability carries CRITICAL, HIGH, MEDIUM, LOW, or UNKNOWN. UNKNOWN means there was no scorable CVSS vector and no GHSA reviewer label — it is not “safe”, and it does not trip a max_severity policy on its own (set policy.deny_unknown_severity to fail on it). Absence of a signal is honest absence, never evidence of low risk.
  • Fix availability — fixed_version is the first version that resolves the advisory. When present, the version is upgradable (the macOS app shows a Fix button per CVE); when absent, there is no published fix yet.
  • Exploitability — when enriched, findings also carry an EPSS score (probability of exploitation) and a KEV flag (CISA Known Exploited Vulnerabilities — actively exploited in the wild). The CLI prints a most-exploitable-first summary (KEV → EPSS → severity); a KEV or ransomware marker means treat it first.
  • Registries — each project lists the registries its packages resolved from, and each dependency’s source_url shows exactly where it came from. This is the basis for registry-enforcement policy (flag anything not from an approved registry). See Policy & registry configuration to set up policy rules, and Registry conventions for the per-ecosystem registry-config reference.
  • Completeness — a scan truthfully carries its own coverage, and a partial scan is never rendered as an unqualified “clean”. A genuine failure — a cataloger that failed or a pipeline gap (scan_incomplete), or degraded vulnerability enrichment — makes the CLI exit non-zero so a CI step can’t stay green on incomplete results. An intentional narrowing is different: a scoped config.languages reports its skipped ecosystems, and a policy scope exclusion keeps the finding visible — these are surfaced honestly but are not failures and do not, by themselves, exit non-zero. Only an affirmatively complete scan with zero findings is clean.

Package Probe can preview and apply dependency upgrades that resolve a vulnerability. Fixing is a Developer-pack (CVE_FIX) capability.

Terminal window
# Preview (dry run) — shows current → target version, the PM command, and each
# CVE the upgrade resolves, with a [MAJOR BUMP] warning where relevant.
packageprobe fix /path/to/project
# Fix a specific advisory
packageprobe fix /path/to/project --cve CVE-2021-23337
# Apply. After each upgrade the project is re-enriched and the targeted advisory
# is re-checked. A fix is reported "Fixed — verified" only when the advisory is
# actually gone; if it persists (the PM resolved a different version, or there is
# no real fix) it reports "applied but NOT confirmed" and the command exits
# non-zero — a still-vulnerable state never reads as success.
packageprobe fix /path/to/project --cve CVE-2021-23337 --apply
# The target may also be a project name or stable id from the last scan — the
# same argument `sbom`/`vex` take. See the CLI reference for the full
# precedence: a directory always wins, a string that is BOTH an existing
# directory and a project living elsewhere is refused rather than guessed, and
# an argument matching neither is a hard error (never a silent no-op).
packageprobe fix my-app

In the macOS app, the Fix Vulns button on a project opens a preview sheet listing every fixable dependency with its current → target version, per-CVE severity, and a major-bump warning. Apply one, or Apply All Fixes to fix the project in bulk; each apply shells out to the native package manager, then rescans.