> ## 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.

# Go - Go modules

> Configure Go to use Root Library Catalog for secure Go modules.

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.

```bash theme={null}
# 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](/rlc/patcher#installation).

Then set your API key:

```bash theme={null}
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/gobinary` 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.

<Note>
  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.
</Note>

## 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:

```bash theme={null}
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:

```bash theme={null}
# Add to ~/.bashrc or ~/.zshrc
export GOPROXY="https://:${ROOTIO_API_KEY}@pkg.root.io/gobinary,https://proxy.golang.org,direct"
```

<Note>
  **No GONOSUMDB 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.

  **GOPRIVATE:** If your project also imports internal/private modules (common in monorepos), set `GOPRIVATE` to cover those module paths so Go doesn't attempt to fetch them through the proxy or checksum database. For example: `export GOPRIVATE="github.com/myorg/internal,*.mycompany.com"`. This is unrelated to Root patches — it applies to any private module your project depends on.
</Note>

## Patching your project

### 1. Preview available patches

Run the patcher in dry-run mode (no `ROOTIO_API_KEY` needed for discovery):

```bash theme={null}
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`:

```bash theme={null}
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:

```bash theme={null}
go build ./...
```

The build will use the patched modules from `pkg.root.io/gobinary` via the `replace` directives.

## Example workflow

```bash theme={null}
# 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:

```go theme={null}
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:

```go theme={null}
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

```yaml theme={null}
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 ./...
```

<Note>
  **No GONOSUMDB needed!** The `go.sum` file committed in your repo contains all the checksums. Go uses those for verification during builds.
</Note>

### GitLab CI

```yaml theme={null}
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

```dockerfile theme={null}
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:

```bash theme={null}
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

| Issue                                         | Solution                                                                                |
| --------------------------------------------- | --------------------------------------------------------------------------------------- |
| `401 Unauthorized`                            | Verify `GOPROXY` includes your `ROOTIO_API_KEY` and the token is valid                  |
| Module not found                              | Confirm the patched module exists at `pkg.root.io/gobinary` or check the dry-run output |
| Checksum mismatch during build                | Ensure `go.sum` is committed and up-to-date - the patcher generates this automatically  |
| Checksum mismatch during manual `go mod tidy` | Set `GONOSUMDB="pkg.root.io"` before running `go mod tidy`                              |
| Pseudo-version dependencies                   | Upgrade to a pinned semver version - the patcher only supports semver                   |
| `replace` not working                         | Ensure `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:

```bash theme={null}
# 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:

```bash theme={null}
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:

```bash theme={null}
# After upgrading dependencies
go get -u github.com/some/module@v2.0.0

# Check for patches
rootio_patcher go remediate
```

## Go Standard Library (stdlib) Limitations

Root Library Catalog does **not** support patching Go's standard library packages (e.g., `net/http`, `crypto/tls`, `encoding/json`). Stdlib packages are part of the Go toolchain itself and cannot be patched using the `replace` directive mechanism that Root uses for external modules.

### Why stdlib patching is not supported

Unlike external Go modules where Root can publish patched versions and use `replace` directives in `go.mod` to redirect module resolution, the Go standard library is:

1. **Embedded in the toolchain** - stdlib packages are compiled from sources bundled with the Go binary itself
2. **Not replaceable via go.mod** - Go's module system does not support `replace` directives for stdlib packages
3. **Tied to the Go version** - The stdlib version is determined by the `go` directive at the top of `go.mod` (e.g., `go 1.22.3`)

### Recommended approach for stdlib vulnerabilities

**Keep your Go version up to date.** Unlike third-party packages where version upgrades may introduce breaking changes, Go's standard library maintains exceptional backwards compatibility.

The Go team at Google maintains stdlib with:

* Strong backwards compatibility guarantees
* Rapid security response times
* Regular patch releases for security issues
* Comprehensive test coverage

**When a stdlib CVE is announced:**

1. Upgrade to the latest patch version of your current Go minor version:
   ```bash theme={null}
   # If on Go 1.22.x, upgrade to latest 1.22.y
   go get go@1.22
   ```

2. Update your `go.mod`:
   ```go theme={null}
   go 1.22.5  // Updated from 1.22.3
   ```

3. For Dockerfile-based builds, update your base image:
   ```dockerfile theme={null}
   # Before
   FROM golang:1.22.3-alpine

   # After
   FROM golang:1.22.5-alpine
   ```

This approach provides the most reliable security posture for stdlib vulnerabilities without compromising build reproducibility.
