Documentation Index
Fetch the complete documentation index at: https://docs.root.io/llms.txt
Use this file to discover all available pages before exploring further.
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:
| Approach | Best for |
|---|
Registry proxy (pkg.root.io) | New projects, CI/CD pipelines, clean installs - point your package manager at Root’s registry and packages arrive patched |
| Patcher CLI | Existing environments, one-shot remediation, or projects where changing global registry config isn’t practical |
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)
curl -sL https://github.com/rootio-avr/rootio_patcher/releases/latest/download/rootio_patcher_linux_x86_64.tar.gz | tar xz
chmod +x rootio_patcher
sudo mv rootio_patcher /usr/local/bin/
macOS (Apple Silicon - M1/M2/M3)
curl -sL https://github.com/rootio-avr/rootio_patcher/releases/latest/download/rootio_patcher_darwin_arm64.tar.gz | tar xz
chmod +x rootio_patcher
sudo mv rootio_patcher /usr/local/bin/
macOS (Intel)
curl -sL https://github.com/rootio-avr/rootio_patcher/releases/latest/download/rootio_patcher_darwin_x86_64.tar.gz | tar xz
chmod +x rootio_patcher
sudo mv rootio_patcher /usr/local/bin/
Windows (PowerShell)
Invoke-WebRequest -Uri "https://github.com/rootio-avr/rootio_patcher/releases/latest/download/rootio_patcher_windows_x86_64.zip" -OutFile "rootio_patcher.zip"
Expand-Archive -Path rootio_patcher.zip -DestinationPath .
# Add rootio_patcher.exe to your PATH or run it directly
Verify
Configuration
| Variable | Required | Default | Description |
|---|
ROOTIO_API_KEY | For pip apply only | - | Your Root API key. Not required for dry-run — the analyze API is public. Required for the Python subcommand when running with --dry-run=false, because the patcher itself reinstalls packages from pkg.root.io. Not required by the patcher for the npm, Maven, or Go subcommands — those rewrite your manifest and rely on your package manager’s existing pkg.root.io registry auth to pull the patched packages. |
ROOTIO_API_URL | No | https://api.root.io | Override Root API endpoint |
ROOTIO_PKG_URL | No | https://pkg.root.io | Override Root package registry |
LOG_LEVEL | No | info | debug, info, warn, or error |
# Needed only for `rootio_patcher pip remediate --dry-run=false`
export ROOTIO_API_KEY="your-api-key-here"
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.
# Preview what would be patched - no API key needed
rootio_patcher pip remediate
# Apply patches (Python: patcher needs ROOTIO_API_KEY because it runs pip install)
export ROOTIO_API_KEY="your-api-key-here"
rootio_patcher pip remediate --dry-run=false
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:
=== DRY-RUN MODE ===
The following operations would be performed:
1. Package: requests @ 2.25.1
Patch (Aliased): rootio-requests @ 2.25.1+root.io.1
CVEs Fixed: [CVE-2023-32681]
Commands:
pip uninstall -y requests
pip install --no-deps --index-url https://root:<key>@pkg.root.io/pypi/simple/ rootio-requests==2.25.1+root.io.1
To apply these patches, run with --dry-run=false
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.
# Preview - no key needed
rootio_patcher pip remediate
# Apply - patcher needs ROOTIO_API_KEY to install from pkg.root.io
export ROOTIO_API_KEY="your-api-key-here"
rootio_patcher pip remediate --dry-run=false
Flags:
| Flag | Default | Description |
|---|
--dry-run | true | Preview changes without applying |
--python-path | python | Path to a specific Python interpreter |
--use-alias | true | Install under Root’s aliased name (e.g., rootio-requests) |
To patch a specific virtual environment:
rootio_patcher pip remediate --python-path=./venv/bin/python --dry-run=false
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.
# npm (default) - no ROOTIO_API_KEY needed
rootio_patcher npm remediate --dry-run=false
# yarn
rootio_patcher npm remediate --package-manager=yarn --dry-run=false
# pnpm
rootio_patcher npm remediate --package-manager=pnpm --dry-run=false
After running the patcher, run your package manager’s install command (this is the step that needs pkg.root.io auth in your .npmrc):
npm install # or yarn install / pnpm install
Flags:
| Flag | Default | Options | Description |
|---|
--dry-run | true | - | Preview changes without applying |
--package-manager | npm | npm, yarn, pnpm | Which package manager to target |
The patcher injects entries in the format npm:@rootio/<package>@<version> into the appropriate override field for your package manager:
| Package manager | Field updated |
|---|
| npm | overrides |
| pnpm | pnpm.overrides |
| Yarn 1 | resolutions |
| Yarn 2+ (Berry) | resolutions |
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.
# Preview - no ROOTIO_API_KEY needed
rootio_patcher maven remediate
# Apply - still no key needed by the patcher itself
rootio_patcher maven remediate --dry-run=false
# Specify a pom.xml path
rootio_patcher maven remediate --file=path/to/pom.xml --dry-run=false
After running the patcher, rebuild (this is the step that needs pkg.root.io auth in your Maven settings.xml):
Flags:
| Flag | Default | Description |
|---|
--dry-run | true | Preview changes without applying |
--file | pom.xml | Path to the target pom.xml |
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.
# Preview - no ROOTIO_API_KEY needed
rootio_patcher go remediate
# Apply - no key needed by the patcher itself; GOPROXY must be configured for go mod tidy to reach pkg.root.io
rootio_patcher go remediate --dry-run=false
# Specify a go.mod path
rootio_patcher go remediate --go-mod=./submodule/go.mod --dry-run=false
After running the patcher, build your project (this is the step that needs GOPROXY to include pkg.root.io):
Flags:
| Flag | Default | Description |
|---|
--dry-run | true | Preview changes without applying |
--go-mod | go.mod | Path to the target go.mod |
Dry-run output shows the exact replace directives that would be added and which CVEs each patch resolves:
=== DRY-RUN MODE ===
The following replace directives would be added to go.mod:
1. replace golang.org/x/net v0.17.0 => pkg.root.io/golang.org/x/net v0.17.0-root.io.1
CVEs Fixed: [CVE-2024-12345]
2. replace github.com/google/uuid v1.3.0 => pkg.root.io/golang/github.com/google/uuid v1.3.0-rootio.1
CVEs Fixed: [CVE-2024-67890]
To apply these patches:
1. Run: rootio_patcher go remediate --dry-run=false
2. Then run: go build ./...
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.
| Exit code | Meaning |
|---|
0 | No patches needed — all packages are up to date |
1 | Error (bad config, API failure, unexpected panic) |
2 | Patches are available — action required |
rootio_patcher npm remediate # --dry-run=true is the default
case $? in
0) echo "All packages are up to date." ;;
2) echo "Patches available — please remediate." ; exit 1 ;;
*) echo "Unexpected error." ; exit 1 ;;
esac
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.
- uses: rootio-avr/rootio_patcher/.github/actions/rootio-patch@main
with:
api-key: ${{ secrets.ROOTIO_API_KEY }}
ecosystem: npm # pip | npm | maven | go | nuget | composer
Inputs:
| Input | Required | Default | Description |
|---|
api-key | Yes | — | Root.io API key |
ecosystem | Yes | — | pip, npm, maven, go, nuget, or composer (Beta) |
working-directory | No | . | Repo subdirectory to run in (e.g. services/api) |
package-manager | No | npm | (npm) npm, yarn, or pnpm |
directory | No | . | (npm) Project directory containing the lock file |
python-path | No | python | (pip) Path to Python interpreter |
use-alias | No | true | (pip) Use Root.io aliased packages |
file | No | pom.xml | (maven) Path to pom.xml |
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:
- uses: rootio-avr/rootio_patcher/.github/actions/rootio-patch@main
env:
ROOTIO_PIP_INDEX_URL: https://my-private-index.example.com/simple/
with:
api-key: ${{ secrets.ROOTIO_API_KEY }}
ecosystem: pip
Outputs:
| Output | Description |
|---|
patches-available | "true" if patches were found, "false" if everything is up to date |
Block a PR if vulnerabilities exist
name: Security Check
on: [pull_request]
jobs:
vuln-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: rootio-avr/rootio_patcher/.github/actions/rootio-patch@main
with:
api-key: ${{ secrets.ROOTIO_API_KEY }}
ecosystem: npm
package-manager: npm
Warn without blocking
- uses: rootio-avr/rootio_patcher/.github/actions/rootio-patch@main
id: vuln-check
continue-on-error: true
with:
api-key: ${{ secrets.ROOTIO_API_KEY }}
ecosystem: npm
- if: steps.vuln-check.outputs.patches-available == 'true'
run: echo "Patches available — consider remediating soon."
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):
- name: Discover available Root patches
run: rootio_patcher pip remediate
Apply - Python (pip): the patcher does the install, so it needs ROOTIO_API_KEY:
- name: Patch vulnerable dependencies
run: rootio_patcher pip remediate --dry-run=false
env:
ROOTIO_API_KEY: ${{ secrets.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):
- name: Patch and install
run: |
rootio_patcher npm remediate --package-manager=npm --dry-run=false
npm install
env:
ROOTIO_API_KEY: ${{ secrets.ROOTIO_API_KEY }}
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:
- name: Patch and build
run: |
rootio_patcher go remediate --dry-run=false
go build ./...
env:
GOPROXY: "https://${{ secrets.ROOTIO_API_KEY }}@pkg.root.io/gobinary,direct"
Option B — .netrc (recommended for Docker builds):
- name: Patch and build
run: |
echo "machine pkg.root.io login token password ${{ secrets.ROOTIO_API_KEY }}" >> ~/.netrc
chmod 600 ~/.netrc
rootio_patcher go remediate --dry-run=false
go build ./...
env:
GOPROXY: "https://pkg.root.io/gobinary,direct"
Source
rootio_patcher is open source under the Apache 2.0 license: github.com/rootio-avr/rootio_patcher