{"record":{"id":"94007ca8981399a3","repo":"github/github-mcp-server","slug":"signing-jwt-w","errorCode":null,"errorMessage":"signing JWT: %w","messagePattern":"signing JWT: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/githubapp/githubapp.go","lineNumber":106,"sourceCode":"\t\t\"iss\": appID,\n\t}\n\n\theaderJSON, err := json.Marshal(header)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"encoding JWT header: %w\", err)\n\t}\n\tclaimsJSON, err := json.Marshal(claims)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"encoding JWT claims: %w\", err)\n\t}\n\n\tsigningInput := base64.RawURLEncoding.EncodeToString(headerJSON) + \".\" +\n\t\tbase64.RawURLEncoding.EncodeToString(claimsJSON)\n\n\tdigest := sha256.Sum256([]byte(signingInput))\n\tsignature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, digest[:])\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"signing JWT: %w\", err)\n\t}\n\n\treturn signingInput + \".\" + base64.RawURLEncoding.EncodeToString(signature), nil\n}\n\ntype installationTokenSource struct {\n\tcfg        Config\n\tprivateKey *rsa.PrivateKey\n\thttpClient *http.Client\n}\n\nfunc newInstallationTokenSource(cfg Config, privateKey *rsa.PrivateKey, httpClient *http.Client) *installationTokenSource {\n\tif httpClient == nil {\n\t\thttpClient = &http.Client{Timeout: httpTimeout}\n\t}\n\treturn &installationTokenSource{cfg: cfg, privateKey: privateKey, httpClient: httpClient}\n}\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/internal/githubapp/githubapp.go#L88-L124","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"tok := provider.AccessToken() // error is logged once, empty string returned\nif tok == \"\" {\n    // check logs; crypto/rand failures are environmental — verify /dev/urandom in the sandbox\n}","preventionTips":["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"],"tags":["crypto","jwt","rsa","environment","rare"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}