Skip to main content
The Root Patcher CLI (rootio_patcher) scans your installed packages, queries Root’s remediation API for available patches, and applies Root-fixed packages to your project - automatically.

When to Use the Patcher

There are two ways to consume Root-patched packages: For Maven specifically, the patcher is the recommended approach - it resolves transitive dependencies and directly updates your pom.xml rather than requiring a full registry mirror configuration.

Installation

Linux (x86_64)

macOS (Apple Silicon - M1/M2/M3)

macOS (Intel)

Windows (PowerShell)

Verify


Configuration

Free discovery, subscription to apply. Root’s /v3/analyze/* endpoints are public, so dry-run discovery has no credential requirements — anyone can run rootio_patcher against their project to see which packages have Root-patched fixes and which CVEs they resolve. Applying those patches still requires a Root subscription, because the patched packages are served from pkg.root.io, which is authenticated.Where the credential lives differs by ecosystem:
  • Python: the patcher does the pip install itself, so it needs ROOTIO_API_KEY set in its environment.
  • npm / Maven / Go: the patcher only rewrites your manifest. Authentication to pkg.root.io is handled by your package manager’s own config (.npmrc, Maven settings.xml, or GOPROXY) when you run npm install, mvn install, or go build ./... after — see the ecosystem sections below.
  • Composer: the patcher rewrites composer.json and runs composer update. Authentication to pkg.root.io/composer/ is passed via COMPOSER_AUTH — see the Composer guide for details.
To get your API key, go to Settings → Token Management in the Root platform and click Generate API Token.

Dry-Run Mode

All commands run in dry-run mode by default - they preview what would change without modifying anything. This is recommended before applying patches for the first time. Dry-run uses Root’s public analyze API and does not require ROOTIO_API_KEY for any ecosystem - you can run it with no Root account at all to discover whether your dependencies have Root patches available.
For --dry-run=false, see the per-ecosystem sections — the patcher itself only needs ROOTIO_API_KEY for pip, since it does the install. For npm and Maven the patcher only rewrites your manifest, and the auth to pkg.root.io is handled by your package manager when you run npm install / mvn install afterwards. Dry-run output shows the exact commands that would be run and which CVEs each patch resolves:

Python - pip

The patcher uses post-install patching: it reads your current environment with pip list, queries Root’s public analyze API for available patches, then uninstalls vulnerable packages and reinstalls Root-patched versions. Because the patcher runs pip install itself against pkg.root.io, applying patches requires ROOTIO_API_KEY to be set in the patcher’s environment. Dry-run does not.
Flags: To patch a specific virtual environment:

JavaScript - npm, yarn, pnpm

The patcher uses pre-install patching: it reads your lock file, queries Root’s public analyze API, then injects overrides or resolutions into your package.json. You run your package manager’s install command afterward to apply the changes. The patcher itself does not need ROOTIO_API_KEY - it only rewrites your manifest. The patched packages are pulled in by the subsequent npm install (or yarn / pnpm), which authenticates to pkg.root.io via your .npmrc - see JavaScript registry setup for configuring that auth.
After running the patcher, run your package manager’s install command (this is the step that needs pkg.root.io auth in your .npmrc):
Flags: The patcher injects entries in the format npm:@rootio/<package>@<version> into the appropriate override field for your package manager:

Java - Maven

The patcher uses pre-install patching: it reads your pom.xml (and any multi-module submodules), queries Root’s public analyze API, then rewrites dependency groupId and version values to use Root-patched equivalents. It also adds <exclusions> to prevent transitive re-introduction of vulnerable versions. The patcher itself does not need ROOTIO_API_KEY - it only rewrites your pom.xml. The patched artifacts are pulled in by the subsequent mvn build, which authenticates to pkg.root.io via your Maven settings.xml - see Maven registry setup for configuring that auth.
After running the patcher, rebuild (this is the step that needs pkg.root.io auth in your Maven settings.xml):
Flags:
For multi-module Maven projects, run the patcher from the root of the project. It will discover all submodule pom.xml files automatically.

Go - Go modules

The patcher uses pre-build patching: it reads your go.mod, queries Root’s public analyze API, then adds replace directives pointing to Root-patched module aliases. After writing go.mod, the patcher automatically runs go mod tidy (and go mod vendor if a vendor directory is present). The patcher itself does not need ROOTIO_API_KEY - it only rewrites your go.mod. The patched modules are downloaded when go mod tidy runs (automatically) and when you build, which authenticates to pkg.root.io. There are two ways to configure that auth:
  • Option A — GOPROXY with embedded credentials: GOPROXY=https://<api-key>@pkg.root.io/gobinary,direct
  • Option B — .netrc: GOPROXY=https://pkg.root.io/gobinary,direct (no credentials in URL) + a ~/.netrc entry: machine pkg.root.io login token password <api-key>
Both options are equivalent. .netrc is preferred for Docker builds because it avoids embedding credentials in a build argument.
Only modules with pinned semver versions (e.g. v1.2.3) are analyzed. Modules using pseudo-versions (e.g. v0.0.0-20230101123456-abcdef012345) are skipped. If you have vulnerable pseudo-versioned dependencies, upgrade them to a pinned release first.
After running the patcher, build your project (this is the step that needs GOPROXY to include pkg.root.io):
Flags: Dry-run output shows the exact replace directives that would be added and which CVEs each patch resolves:

Ignoring Packages

You can exclude specific package@version pairs from patching. Ignored entries are sent to Root’s analyze API as an exclusion list, so they are skipped during analysis and never appear in dry-run output or get patched on apply. This is useful when a patch is known to break your build, when your security team has formally accepted the risk for a particular dependency, or when you want to scope remediation to a controlled subset. The ignore list is supported on every ecosystem subcommand (pip, npm, maven, go, nuget, composer) and is assembled from two sources, which are merged and de-duplicated.

The --ignore flag

Pass one or more package@version entries. The flag is repeatable and also accepts a comma-separated list:

The .rootioignore file

For a persistent, committed ignore list, create a .rootioignore file with one package@version per line. Blank lines and lines beginning with # are skipped:
The patcher reads .rootioignore automatically from the directory of the manifest it is patching: If no .rootioignore file is present, it is silently skipped. Entries from the file and from --ignore flags are combined.
Matching is exact on both name and version — django@4.2.0 ignores only that version. django@4.2.1 would still be analyzed and patched.

Vulnerability Gate

Running rootio_patcher in dry-run mode (the default) is non-destructive — it checks for available patches and exits with a code that indicates the result. Use this to fail a pipeline or trigger an alert without touching any files.

CI/CD

Dry-run discovery has no credential requirements. For apply, the credential lives in different places depending on ecosystem - on the patcher for pip, on the package manager step for npm and Maven.

GitHub Action

A reusable composite action runs the vulnerability gate — it calls rootio_patcher in dry-run mode and fails the job if patches are available. No files are modified.
Inputs: Advanced settings (ROOTIO_API_URL, ROOTIO_PKG_URL, ROOTIO_PIP_INDEX_URL, LOG_LEVEL) are not inputs — pass them as environment variables on the calling step:
Outputs:

Block a PR if vulnerabilities exist

Warn without blocking

Apply patches in CI

To remediate (not just check), run the patcher with --dry-run=false and commit the result: Dry-run discovery (any ecosystem, no Root subscription needed):
Apply - Python (pip): the patcher does the install, so it needs ROOTIO_API_KEY:
Apply - npm: the patcher rewrites package.json with no key; the following npm install authenticates to pkg.root.io via your .npmrc (which can use ${ROOTIO_API_KEY} for the registry token):
Apply - Maven: same shape — the patcher edits pom.xml with no key; the subsequent mvn step authenticates via your settings.xml. Apply - Go: the patcher rewrites go.mod and auto-runs go mod tidy. Configure GOPROXY to include pkg.root.io and supply credentials via one of these options: Option A — GOPROXY with embedded credentials:
Option B — .netrc (recommended for Docker builds):

Source

rootio_patcher is open source under the Apache 2.0 license: github.com/rootio-avr/rootio_patcher