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
- Check the wrapped error: if it mentions the random reader or entropy, verify /dev/urandom exists and is readable inside the container
- Re-download the .pem from the GitHub App settings and retry with a known-good key to rule out key corruption
- If running under a sandbox/seccomp profile, allow the getrandom(2) syscall or mount a working /dev/urandom
- 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
- In locked-down containers/sandboxes, confirm the getrandom syscall is allowed and /dev/urandom is mounted
- Smoke-test auth at startup rather than at first API call so entropy problems surface during deploy
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
- private key is %T, want an RSA key
- installation token request failed: %s (reading response: %w)
- callback server: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/94007ca8981399a3.
Report an issue: GitHub.