Skip to main content

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.

Root Library Catalog supports Go modules. Patched modules are served through the GOPROXY protocol and consumed via replace directives in your go.mod file.

Prerequisites

The Root Patcher CLI (rootio_patcher) is required to analyze your dependencies and inject the necessary replace directives. Install it before configuring your Go environment.
# macOS (Apple Silicon)
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/

# 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/
For macOS Intel and Windows, see the full installation instructions. Then set your API key:
export ROOTIO_API_KEY="your-api-key-here"

How Root Go modules work

Go modules are patched in a Docker build environment and published to pkg.root.io/go via the GOPROXY protocol. Patched modules keep their original module identity (e.g., module github.com/google/uuid) and are consumed using Go’s native replace directive in go.mod, requiring zero changes to application source code. Root publishes patched modules with the same version plus a -rootio.N suffix. For example:
golang.org/x/net v0.17.0 → pkg.root.io/golang/golang.org/x/net v0.17.0-rootio.1
The patcher analyzes your go.mod, queries Root’s API for available patches, and adds replace directives pointing to the Root-patched versions.
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.

Authentication

Go’s module proxy system authenticates via the GOPROXY environment variable. This is the only environment variable you need to configure for regular builds:
export GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"
This tells Go to:
  1. Try resolving modules from pkg.root.io/gobinary first (with authentication)
  2. Fall back to the public Go proxy at https://proxy.golang.org
  3. Finally fall back to direct for modules not available through either proxy
You can also set this persistently:
# Add to ~/.bashrc or ~/.zshrc
export GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"
No GONOSUMDB or GOPRIVATE needed! Once the patcher runs go mod tidy and generates your go.sum file, regular builds use the checksums from go.sum for verification. Go only queries the checksum database when adding new modules, which the patcher handles internally.

Patching your project

1. Preview available patches

Run the patcher in dry-run mode (no ROOTIO_API_KEY needed for discovery):
rootio_patcher go remediate
This shows which modules have Root-patched versions available and which CVEs they fix.

2. Apply patches

Run the patcher with --dry-run=false to update your go.mod:
rootio_patcher go remediate --dry-run=false
The patcher will:
  1. Add replace directives to your go.mod
  2. Automatically run go mod tidy to fetch the patched modules
  3. Run go mod vendor if a vendor/ directory exists

3. Build your project

After patching, build as usual:
go build ./...
The build will use the patched modules from pkg.root.io/go via the replace directives.

Example workflow

# 1. Configure GOPROXY (only env var needed for builds)
export GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"

# 2. Preview patches (dry-run)
rootio_patcher go remediate

# Output:
# === 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/golang.org/x/net v0.17.0-rootio.1
#    CVEs Fixed: [CVE-2024-12345]
#
# 2. replace github.com/golang-jwt/jwt/v4 v4.5.0 => pkg.root.io/golang/github.com/golang-jwt/jwt/v4 v4.5.0-rootio.1
#    CVEs Fixed: [CVE-2024-67890]

# 3. Apply patches
# The patcher automatically runs `go mod tidy` and updates go.sum
rootio_patcher go remediate --dry-run=false

# 4. Commit the changes
# IMPORTANT: Commit both go.mod and go.sum
git add go.mod go.sum
git commit -m "Apply Root patches for Go modules"

# 5. Build (go.sum provides checksum verification)
go build ./...

Working with go.mod

After running the patcher, your go.mod will contain replace directives like:
module github.com/myorg/myapp

go 1.21

require (
    golang.org/x/net v0.17.0
    github.com/golang-jwt/jwt/v4 v4.5.0
)

// Root patches
replace golang.org/x/net v0.17.0 => pkg.root.io/golang/golang.org/x/net v0.17.0-rootio.1
replace github.com/golang-jwt/jwt/v4 v4.5.0 => pkg.root.io/golang/github.com/golang-jwt/jwt/v4 v4.5.0-rootio.1
Your import statements remain unchanged:
import (
    "golang.org/x/net/http2"
    "github.com/golang-jwt/jwt/v4"
)
The replace directives transparently redirect module resolution to Root’s patched versions at build time.

CI/CD Configuration

In CI/CD environments, you only need to set GOPROXY - the committed go.sum file provides checksum verification.

GitHub Actions

name: Build

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-go@v5
        with:
          go-version: '1.21'
      
      - name: Configure GOPROXY
        run: echo "GOPROXY=https://:${{ secrets.ROOTIO_API_KEY }}@pkg.root.io/gobinary,https://proxy.golang.org,direct" >> $GITHUB_ENV
      
      - name: Build
        run: go build ./...
No GONOSUMDB needed! The go.sum file committed in your repo contains all the checksums. Go uses those for verification during builds.

GitLab CI

build:
  image: golang:1.21
  before_script:
    - export GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"
  script:
    - go build ./...

Docker builds

FROM golang:1.21-alpine

WORKDIR /app

# Copy go.mod, go.sum (contains checksums)
COPY go.mod go.sum ./

# Set GOPROXY - no GONOSUMDB needed
ARG ROOTIO_API_KEY
ENV GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"

# Download dependencies (verified against go.sum)
RUN go mod download

# Copy source and build
COPY . .
RUN go build -o myapp ./cmd/myapp

CMD ["./myapp"]

Checksum verification and go.sum

Go’s module system uses checksums for security. Here’s how it works with Root patches:

How go.sum provides security

When the Root Patcher runs go mod tidy, it:
  1. Downloads the patched modules from pkg.root.io/gobinary
  2. Calculates their checksums
  3. Writes those checksums to your go.sum file
During regular builds (go build, go test, Docker builds):
  • Go reads the checksums from your committed go.sum file
  • Go downloads modules and verifies them against go.sum
  • Go does not query the checksum database (sum.golang.org)
  • Your go.sum is the source of truth
This means:
  • ✅ Cryptographic verification is still active via go.sum
  • ✅ No environment variables needed beyond GOPROXY
  • ✅ Reproducible builds across all environments
  • ✅ Git tracks the checksums (commit go.sum with your code)

When GONOSUMDB is used

The Root Patcher sets GONOSUMDB=pkg.root.io internally when it runs go mod tidy. This allows it to download patched modules from Root’s registry without querying the public checksum database. You don’t need to set this yourself - the patcher handles it automatically.

If you manually run go mod tidy

If you need to run go mod tidy manually after the patcher has added replace directives:
export GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"
export GONOSUMDB="pkg.root.io"
go mod tidy
But this is rarely needed - the patcher runs go mod tidy automatically after updating your go.mod.

Troubleshooting

IssueSolution
401 UnauthorizedVerify GOPROXY includes your ROOTIO_API_KEY and the token is valid
Module not foundConfirm the patched module exists at pkg.root.io/gobinary or check the dry-run output
Checksum mismatch during buildEnsure go.sum is committed and up-to-date - the patcher generates this automatically
Checksum mismatch during manual go mod tidySet GONOSUMDB="pkg.root.io" before running go mod tidy
Pseudo-version dependenciesUpgrade to a pinned semver version - the patcher only supports semver
replace not workingEnsure go mod tidy has been run and GOPROXY is configured before building

Multi-module projects

For projects with multiple Go modules (e.g., monorepos), run the patcher from the root and specify each module:
# Patch the root module
rootio_patcher go remediate --go-mod=./go.mod --dry-run=false

# Patch a submodule
rootio_patcher go remediate --go-mod=./services/api/go.mod --dry-run=false
Or iterate over all modules:
find . -name "go.mod" -execdir rootio_patcher go remediate --dry-run=false \;

Version pinning

Root patches are tied to specific upstream versions. If you upgrade a dependency to a newer version, run the patcher again to check if a Root patch is available for the new version:
# After upgrading dependencies
go get -u github.com/some/module@v2.0.0

# Check for patches
rootio_patcher go remediate