pkgradar 0.8.0

PkgRadar CI gate and static package scanner
pkgradar-0.8.0 is not a library.

pkgradar-cli

PkgRadar's CI gate and static package scanner as a single binary, plus the GitHub Actions composite that wraps it.

pkgradar gate --lockfile package-lock.json --fail-on high

This repo is the entire installable surface area for the gate. Fork, vendor, audit, or run it as-is — there's no closed-source path to the binary you run.

Install

Prebuilt binaries

Each release tag (v0.1.0+) attaches binaries for:

  • pkgradar-x86_64-unknown-linux-gnu.tar.gz
  • pkgradar-aarch64-unknown-linux-gnu.tar.gz
  • pkgradar-x86_64-apple-darwin.tar.gz
  • pkgradar-aarch64-apple-darwin.tar.gz
TAG=$(curl -sSfL https://api.github.com/repos/PkgRadar/pkgradar-cli/releases/latest \
  | grep '"tag_name"' | head -1 | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
ARCH=$(uname -m); OS=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$OS-$ARCH" in
  linux-x86_64)   ASSET="pkgradar-x86_64-unknown-linux-gnu.tar.gz" ;;
  linux-aarch64)  ASSET="pkgradar-aarch64-unknown-linux-gnu.tar.gz" ;;
  darwin-x86_64)  ASSET="pkgradar-x86_64-apple-darwin.tar.gz" ;;
  darwin-arm64)   ASSET="pkgradar-aarch64-apple-darwin.tar.gz" ;;
esac
curl -sSfL "https://github.com/PkgRadar/pkgradar-cli/releases/download/${TAG}/${ASSET}" \
  | tar -xz
sudo install -m 0755 pkgradar /usr/local/bin/

From crates.io

cargo install pkgradar --locked

From source

git clone https://github.com/PkgRadar/pkgradar-cli
cd pkgradar-cli
cargo install --path . --locked

GitHub Actions

The composite action lives at the root of this repo, so you can use it directly without specifying a subpath:

- uses: PkgRadar/pkgradar-cli@v1
  with:
    token: ${{ secrets.PKGRADAR_TOKEN }}
    fail-on: high
    # lockfile: pnpm-lock.yaml   # optional override; auto-detects otherwise
Input Required Default Meaning
token yes API token from https://pkgradar.com/dashboard/keys
lockfile no auto Path to a lockfile. Auto-detects npm/pnpm/yarn-classic, pip/pipenv/poetry/uv/pdm in the working dir.
fail-on no high Block on this risk level or worse (low, review, high)
config no Path to a .pkgradar.yml config file
fail-open no true Exit 0 on transport-level API errors (timeout, 5xx). Set false to harden.
version no latest Pin a specific pkgradar CLI version, e.g. v0.1.0
base-url no Override https://pkgradar.com (self-hosted only)

The action prefers a prebuilt binary from this repo's releases for fast cold-start (~10s) and falls back to cargo install when the runner platform isn't in the release matrix.

GitLab CI

A ready-made template is hosted on pkgradar.com:

include:
  - remote: 'https://pkgradar.com/templates/pkgradar.gitlab-ci.yml'

pkgradar-gate:
  extends: .pkgradar-base
  stage: test
  variables:
    PKGRADAR_FAIL_ON: high

PKGRADAR_TOKEN must be set in Settings → CI/CD → Variables.

Configure

export PKGRADAR_TOKEN="rps_..."
export PKGRADAR_BASE_URL="https://pkgradar.com"   # optional

Or commit a .pkgradar.yml at the root of your repo:

fail_on: high
timeout_ms: 30000
fail_open: true
allowlist:
  - "@types/node@22.5.4"   # reviewed and approved internally
watchlist:
  - "react@18.3.1"

CLI flags override the config file on conflict.

Commands

pkgradar gate

Asks the gate endpoint whether each spec should be blocked. Exits non-zero when any spec breaches --fail-on. Combine with --lockfile to batch every transitive in one call.

pkgradar gate lodash@4.17.21 left-pad@1.3.0 --fail-on high
pkgradar gate --lockfile pnpm-lock.yaml --fail-on review

pkgradar scan

Returns the full scan report rather than the gate decision. Use this when you want to see why a release would be blocked.

pkgradar scan @scope/name@1.2.3 --format json | jq '.[0].findings'
pkgradar scan --lockfile yarn.lock --format json

pkgradar version

Prints the binary version and the resolved API endpoint.

Lockfile support

npm ecosystem

Format Supported
package-lock.json v1 Yes
package-lock.json v2 Yes
package-lock.json v3 Yes
npm-shrinkwrap.json Yes
pnpm-lock.yaml v6+ Yes
yarn.lock v1 Yes
yarn.lock v2+ (Berry) No — errors with a hint

PyPI ecosystem

Format Supported
requirements.txt Yes — only fully-pinned (==) entries are gated
requirements.lock (pip-tools) Yes
constraints.txt Yes
Pipfile.lock Yes (default + develop sections)
poetry.lock Yes
uv.lock Yes
pdm.lock Yes

RubyGems ecosystem

Format Supported
Gemfile.lock Yes (GEM block, registry-resolved pins; GIT/PATH/PLUGIN sources skipped)
gems.locked Yes

Cargo (Rust / crates.io) ecosystem

Format Supported
Cargo.lock Yes (registry+ and sparse+ sources; git+ and workspace crates skipped)

Maven (Java / Maven Central) ecosystem

Format Supported
pom.xml Yes — <dependency> blocks with concrete pinned versions; ${prop} / [1,2) ranges skipped, <dependencyManagement> ignored

Maven specs use the groupId:artifactId@version shape, e.g. com.fasterxml.jackson.core:jackson-databind@2.17.0.

NuGet (.NET / nuget.org) ecosystem

Format Supported
packages.lock.json Yes (PackageReference lockfile; type: Project entries skipped)
packages.config Yes (legacy XML format)
project.assets.json Yes (resolved restore graph; type: project entries skipped)

NuGet specs use Id@Version, e.g. Newtonsoft.Json@13.0.3. IDs are case-insensitive on the registry.

Composer (PHP / Packagist) ecosystem

Format Supported
composer.lock Yes (packages + packages-dev arrays; metapackage and dev-* refs skipped)

Composer specs use vendor/name@version, e.g. symfony/console@v6.4.1.

The parser deduplicates by (ecosystem, name, version), normalizes PyPI names per PEP 503, and skips non-registry refs (file:, link:, workspace:, git+, github:, direct URL specs).

Fail-open behaviour

Network or transport-level errors (timeout, 5xx, DNS) print a warning and exit 0 by default — security tooling shouldn't take down a deploy pipeline because PkgRadar had a 30-second blip. Set fail_open: false in .pkgradar.yml (or pass --no-fail-open) once your gate cadence is stable.

Exit codes

Code Meaning
0 All specs passed the gate.
1 At least one spec was blocked.
2 Usage / config error (missing token, bad flag).
3 Network, TLS, or installer failure.

Building locally

cargo build --release
./target/release/pkgradar --help
cargo test --release

The binary is statically linked against rustls-tls-native-roots, so it picks up the host's CA bundle and doesn't link OpenSSL at runtime.

License

Apache-2.0. See LICENSE.