{"record":{"id":"1b5e8cf47d5fe5c6","repo":"cilium/cilium","slug":"pem-format-error-in-tls-key","errorCode":null,"errorMessage":"PEM format error in TLS Key","messagePattern":"PEM format error in TLS Key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"operator/pkg/gateway-api/status_listener.go","lineNumber":672,"sourceCode":"\n\treturn res\n}\n\nfunc (m *ListenerStatusManager) validateTLSSecret(ctx context.Context, namespace, name string) error {\n\tsecret := &corev1.Secret{}\n\tif err := m.client.Get(ctx, client.ObjectKey{\n\t\tNamespace: namespace,\n\t\tName:      name,\n\t}, secret); err != nil {\n\t\treturn err\n\t}\n\n\tif !helpers.IsValidPemFormat(secret.Data[corev1.TLSCertKey]) {\n\t\treturn fmt.Errorf(\"PEM format error in TLS Certificate\")\n\t}\n\n\tif !helpers.IsValidPemFormat(secret.Data[corev1.TLSPrivateKeyKey]) {\n\t\treturn fmt.Errorf(\"PEM format error in TLS Key\")\n\t}\n\treturn nil\n}\n\nfunc (m *ListenerStatusManager) filterOutInvalidListeners(ctx context.Context, listeners []ingestion.ListenerWithContext, grants []gatewayv1.ReferenceGrant) ([]ingestion.ListenerWithContext, []ingestion.ListenerWithContext) {\n\tvalid := make([]ingestion.ListenerWithContext, 0, len(listeners))\n\tinvalid := make([]ingestion.ListenerWithContext, 0, len(listeners))\n\tfor _, listener := range listeners {\n\t\tres := m.validateListener(ctx, listener.Listener, listenerValidationParams{\n\t\t\townerNamespace: listener.Source.Namespace,\n\t\t\townerKind:      listener.Source.Kind,\n\t\t\tgeneration:     listener.SourceGeneration,\n\t\t\tgrants:         grants,\n\t\t\townerRef: types.NamespacedName{\n\t\t\t\tName:      listener.Source.Name,\n\t\t\t\tNamespace: listener.Source.Namespace,\n\t\t\t}.String(),\n\t\t})","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/operator/pkg/gateway-api/status_listener.go#L654-L690","documentation":"validateTLSSecret checks that both the TLS certificate and private key stored in a Kubernetes TLS-type Secret are valid PEM-encoded data before the Gateway listener uses them. This error means the Secret's tls.key entry failed helpers.IsValidPemFormat — it is empty, malformed, or not PEM armored. The controller rejects the listener so it is not programmed with an unusable key.","triggerScenarios":"A Secret of type kubernetes.io/tls referenced by a Gateway listener's certificateRefs has a tls.key value that is empty, base64 garbage, truncated, or lacks PEM '-----BEGIN ... PRIVATE KEY-----' markers.","commonSituations":"Secrets created by cert-manager or manually with a raw key pasted without headers; keys converted to PKCS#8/PKCS#1 without armor; typo of tls.key field name; Secret synced from another namespace without the key portion; whitespace/encoding corruption in GitOps pipelines.","solutions":["Fix the Secret's tls.key field to contain a complete PEM block including -----BEGIN ... PRIVATE KEY----- and -----END ... PRIVATE KEY----- lines","Recreate the TLS Secret with kubectl create secret tls <name> --cert=cert.pem --key=key.pem","Verify the certificateRefs on the Gateway listener point to the correct Secret name and namespace","If using cert-manager, check the Certificate resource status for issuance errors and let it re-issue the key pair"],"exampleFix":"// before: key stored without PEM armor\ndata:\n  tls.key: MIIJKQIBAAKC...   # raw DER, no headers\n// after\ndata:\n  tls.key: <base64 of full PEM:\n    -----BEGIN PRIVATE KEY-----\n    ...\n    -----END PRIVATE KEY----->","handlingStrategy":"validation","validationCode":"// Before referencing the Secret in a Gateway listener\nfor _, k := range []string{\"tls.crt\", \"tls.key\"} {\n    data, ok := secret.Data[k]\n    if !ok || !bytes.Contains(data, []byte(\"-----BEGIN \")) {\n        return fmt.Errorf(\"secret %s/%s: %s is not PEM encoded\", secret.Namespace, secret.Name, k)\n    }\n}","typeGuard":"func hasPEMBlock(data []byte) bool {\n    block, _ := pem.Decode(data)\n    return block != nil\n}","tryCatchPattern":null,"preventionTips":["Create TLS Secrets with kubectl create secret tls rather than hand-crafting base64","Use cert-manager to issue and rotate certificates automatically","Lint manifests in CI to assert kubernetes.io/tls Secrets contain both keys with PEM markers","Verify certificateRefs point at the right Secret name/namespace before applying Gateways"],"tags":["tls","kubernetes","gateway-api","pem"],"backgroundTag":"invalid-tls-secret-pem","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}