oauth2-proxy/oauth2-proxy · error

SystemCertPool is empty

Error message

SystemCertPool is empty

What it means

getSystemCertPool wraps x509.SystemCertPool() and returns this error when Go's certificate pool comes back nil instead of a usable (possibly empty) pool. On some platforms (notably older Go versions on Windows or stripped-down Linux images) the system root store cannot be loaded, yielding a nil pool. The library refuses to continue building a TLS trust pool from nothing.

Source

Thrown at pkg/util/util.go:47

			return nil, fmt.Errorf("unable to get SystemCertPool when append is true - #{err}")
		}
		pool = rootPool
	} else {
		pool = x509.NewCertPool()
	}

	return loadCertsFromPaths(paths, pool)

}

func getSystemCertPool() (*x509.CertPool, error) {
	rootPool, err := x509.SystemCertPool()
	if err != nil {
		return nil, err
	}

	if rootPool == nil {
		return nil, fmt.Errorf("SystemCertPool is empty")
	}

	return rootPool, nil
}

func loadCertsFromPaths(paths []string, pool *x509.CertPool) (*x509.CertPool, error) {
	for _, path := range paths {
		// Cert paths are a configurable option
		data, err := os.ReadFile(path) // #nosec G304
		if err != nil {
			return nil, fmt.Errorf("certificate authority file (%s) could not be read - %s", path, err)
		}
		if !pool.AppendCertsFromPEM(data) {
			return nil, fmt.Errorf("loading certificate authority (%s) failed", path)
		}
	}
	return pool, nil
}

View on GitHub (pinned to 33c2eb92de)

Solutions

  1. Install system CA certificates (e.g. apt-get install ca-certificates or apk add ca-certificates) so the system trust store exists
  2. Upgrade Go to a recent version where x509.SystemCertPool reliably returns a non-nil pool
  3. Pass explicit CA file paths via the cert pool path configuration so pool construction does not depend on the system store
  4. Check the underlying x509 error returned before this message for the real platform cause

Example fix

// before
rootPool, err := x509.SystemCertPool()
if err != nil {
    return nil, err
}
// after (fallback to an empty pool and load explicit CAs)
rootPool, err := x509.SystemCertPool()
if err != nil || rootPool == nil {
    rootPool = x509.NewCertPool()
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := x509.SystemCertPool(); err != nil || rootPoolNil() { /* install CA certs before starting */ }
func rootPoolNil() bool { p, _ := x509.SystemCertPool(); return p == nil }

Type guard

func systemPoolAvailable() bool { p, _ := x509.SystemCertPool(); return p != nil }

Prevention

When it happens

Trigger: GetCertPool -> getSystemCertPool when x509.SystemCertPool() returns (nil, nil), which happens on platforms where the system cert store is unavailable or on Go versions with platform-specific cert-loading bugs.

Common situations: Running in a minimal/alpine or scratch Docker image without ca-certificates installed; Windows or macOS with an empty/unreadable system trust store; older Go runtimes with known x509 SystemCertPool bugs.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of oauth2-proxy/oauth2-proxy@33c2eb92de (2026-09-06). Data as JSON: /api/errors/20664ce0164c58cc. Report an issue: GitHub.