github/github-mcp-server · error

signing JWT: %w

Error message

signing JWT: %w

What it means

rsa.SignPKCS1v15 failed while signing the RS256 JWT for the installation-token request. Because the key already passed x509 parsing, a structurally invalid key is essentially impossible here; real-world failures come from the entropy source (crypto/rand) being unavailable or a key whose internal state is corrupt. It is a rare, low-level crypto failure surfaced with %w so the underlying error text identifies the reader at fault.

Source

Thrown at internal/githubapp/githubapp.go:106

		"iss": appID,
	}

	headerJSON, err := json.Marshal(header)
	if err != nil {
		return "", fmt.Errorf("encoding JWT header: %w", err)
	}
	claimsJSON, err := json.Marshal(claims)
	if err != nil {
		return "", fmt.Errorf("encoding JWT claims: %w", err)
	}

	signingInput := base64.RawURLEncoding.EncodeToString(headerJSON) + "." +
		base64.RawURLEncoding.EncodeToString(claimsJSON)

	digest := sha256.Sum256([]byte(signingInput))
	signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, digest[:])
	if err != nil {
		return "", fmt.Errorf("signing JWT: %w", err)
	}

	return signingInput + "." + base64.RawURLEncoding.EncodeToString(signature), nil
}

type installationTokenSource struct {
	cfg        Config
	privateKey *rsa.PrivateKey
	httpClient *http.Client
}

func newInstallationTokenSource(cfg Config, privateKey *rsa.PrivateKey, httpClient *http.Client) *installationTokenSource {
	if httpClient == nil {
		httpClient = &http.Client{Timeout: httpTimeout}
	}
	return &installationTokenSource{cfg: cfg, privateKey: privateKey, httpClient: httpClient}
}

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Check the wrapped error: if it mentions the random reader or entropy, verify /dev/urandom exists and is readable inside the container
  2. Re-download the .pem from the GitHub App settings and retry with a known-good key to rule out key corruption
  3. If running under a sandbox/seccomp profile, allow the getrandom(2) syscall or mount a working /dev/urandom
  4. Retry once at startup — a transient entropy starvation on early boot resolves itself
Defensive patterns

Strategy: try-catch

Try / catch

tok := provider.AccessToken() // error is logged once, empty string returned
if tok == "" {
    // check logs; crypto/rand failures are environmental — verify /dev/urandom in the sandbox
}

Prevention

When it happens

Trigger: mintJWT calls rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, digest) at internal/githubapp/githubapp.go:104 and the call returns non-nil. This happens when crypto/rand cannot read from the OS entropy source (e.g. /dev/urandom unavailable in a locked-down sandbox) or the parsed RSA key contains invalid precomputed values.

Common situations: Running inside a minimal container or gVisor/Kata sandbox where /dev/urandom is not wired in; a key file corrupted on disk in a way x509 parsing tolerated; extremely rare memory corruption. On normal hosts this error is almost never seen.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/94007ca8981399a3. Report an issue: GitHub.