{"record":{"id":"4529add8193be602","repo":"kubernetes/kops","slug":"decoding-pem-public-key","errorCode":null,"errorMessage":"decoding pem public key","messagePattern":"decoding pem public key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops-controller/pkg/server/server.go","lineNumber":293,"sourceCode":"\t\tcert, err := s.issueCert(ctx, name, pubKey, id, validHours, req.KeypairIDs)\n\t\tif err != nil {\n\t\t\tklog.Infof(\"bootstrap %s cert %q issue err: %v\", r.RemoteAddr, name, err)\n\t\t\tw.WriteHeader(http.StatusBadRequest)\n\t\t\t_, _ = fmt.Fprintf(w, \"failed to issue %q: %v\", name, err)\n\t\t\treturn\n\t\t}\n\t\tresp.Certs[name] = cert\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t_ = json.NewEncoder(w).Encode(resp)\n\tklog.Infof(\"bootstrap %s (req.includeNodeConfig: %t, req.certs.#: %d, req.keypairs.#: %d) success\", r.RemoteAddr, req.IncludeNodeConfig, len(req.Certs), len(req.KeypairIDs))\n}\n\nfunc (s *Server) issueCert(ctx context.Context, name string, pubKey string, id *bootstrap.VerifyResult, validHours uint32, keypairIDs map[string]string) (string, error) {\n\tblock, _ := pem.Decode([]byte(pubKey))\n\tif block == nil {\n\t\treturn \"\", fmt.Errorf(\"decoding pem public key\")\n\t}\n\tif block.Type != \"RSA PUBLIC KEY\" {\n\t\treturn \"\", fmt.Errorf(\"unexpected key type %q\", block.Type)\n\t}\n\tkey, err := x509.ParsePKIXPublicKey(block.Bytes)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"parsing key: %v\", err)\n\t}\n\n\tissueReq := &pki.IssueCertRequest{\n\t\tSigner:    fi.CertificateIDCA,\n\t\tType:      \"client\",\n\t\tPublicKey: key,\n\t\tValidity:  time.Hour * time.Duration(validHours),\n\t}\n\n\tif !s.certNames.Has(name) {\n\t\treturn \"\", fmt.Errorf(\"key name not enabled\")","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops-controller/pkg/server/server.go#L275-L311","documentation":"issueCert receives a PEM-encoded public key from the bootstrap request. This error is thrown when pem.Decode cannot parse any PEM block from the submitted key material, i.e. the payload is not valid PEM.","triggerScenarios":"A bootstrap client posts a cert request whose pubKey field is empty, base64-corrupted, or otherwise not PEM-encoded, so pem.Decode returns block == nil.","commonSituations":"Node-side nodeup version mismatch producing non-PEM key format; key truncated or double-encoded in transit; malicious/garbage requests against the bootstrap endpoint.","solutions":["Log the offending request source and regenerate the key on the node","Confirm nodeup and kops-controller versions match","Ensure the client sends the PEM text (with BEGIN/END headers) not raw DER","Check any proxies/mutating layers for truncation"],"exampleFix":"// before\npayload[\"publicKey\"] = string(derBytes)\n// after\npayload[\"publicKey\"] = string(pem.EncodeToMemory(&pem.Block{Type: \"RSA PUBLIC KEY\", Bytes: derBytes}))","handlingStrategy":"validation","validationCode":"if !strings.HasPrefix(pubKey, \"-----BEGIN \") {\n    return fmt.Errorf(\"public key is not PEM-encoded\")\n}","typeGuard":"func isPEMBlock(s string) bool {\n    b, _ := pem.Decode([]byte(s))\n    return b != nil\n}","tryCatchPattern":"block, _ := pem.Decode([]byte(pubKey))\nif block == nil {\n    return \"\", fmt.Errorf(\"decoding pem public key\")\n}","preventionTips":["Always PEM-encode keys before sending bootstrap requests","Verify key bytes are not truncated by HTTP middleware","Keep nodeup and kops-controller in lockstep versions"],"tags":["go","pem","tls","certificates","bootstrap"],"backgroundTag":"invalid-pem-key","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}