{"record":{"id":"752ca8e7f09b4692","repo":"cloudflare/pingora","slug":"invalid-ca-pem","errorCode":null,"errorMessage":"invalid ca pem","messagePattern":"invalid ca pem","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pingora-core/src/listeners/tls/s2n/mod.rs","lineNumber":85,"sourceCode":"        if let Some(alpn) = self.alpn {\n            builder\n                .set_application_protocol_preference(alpn.to_wire_protocols())\n                .unwrap();\n        }\n\n        if let (Some(cert_path), Some(key_path)) = (self.cert_path, self.key_path) {\n            let Ok((cert, key)) = load_certs_and_key_files(&cert_path, &key_path) else {\n                panic!(\n                    \"Failed to load provided certificates \\\"{}\\\" or key \\\"{}\\\".\",\n                    cert_path, key_path\n                )\n            };\n\n            builder.load_pem(&cert, &key).unwrap();\n        }\n\n        if let Some(ca) = self.ca {\n            builder.trust_pem(&ca.raw_pem).expect(\"invalid ca pem\");\n        }\n\n        if !self.verify_client_hostname {\n            builder\n                .set_verify_host_callback(IgnoreVerifyHostnameCallback::new())\n                .unwrap();\n        }\n\n        let config = builder.build().unwrap();\n        let connection_builder = S2NConnectionBuilder {\n            config,\n            psk_config: self.psk_config.clone(),\n            security_policy: Some(policy.clone()),\n        };\n\n        Acceptor {\n            acceptor: TlsAcceptor::new(connection_builder),\n            offload: self.offload_threadpool.map(|(shards, threads_per_shard)| {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/cloudflare/pingora/blob/0046038bd402bc82912da862dadf9a479f31e9f1/pingora-core/src/listeners/tls/s2n/mod.rs#L67-L103","documentation":"When the s2n TLS listener settings include a CA (mutual-TLS client verification), TlsSettings::build() calls builder.trust_pem(&ca.raw_pem) and .expect()s success (pingora-core/src/listeners/tls/s2n/mod.rs:85). If s2n-tls cannot parse the supplied PEM (DER bytes, truncated text, wrong block type, empty file), the expect panics with 'invalid ca pem' while the acceptor is being built, i.e. at listener startup.","triggerScenarios":"Building with the s2n feature and constructing TlsSettings with a CA (client cert verification / add_ca style API) whose raw PEM bytes are not a parseable PEM certificate chain.","commonSituations":"Certificates exported as DER instead of PEM; copy-paste that dropped the BEGIN/END lines or inserted whitespace; pointing at a bundle with non-certificate blocks; a CI cert-generation script changing format between environments.","solutions":["Re-export the CA in PEM format: openssl x509 -inform der -in ca.der -out ca.pem","Sanity-check the file parses before deploying: openssl x509 -in ca.pem -noout -text","Ensure the PEM contains CERTIFICATE blocks only (keys/cross-signed extras can confuse parsers)"],"exampleFix":"# before: DER file or corrupted PEM passed as the s2n CA\nca.pem: \"MII...\" # base64 DER without -----BEGIN CERTIFICATE-----\n\n# after: convert and verify\nopenssl x509 -inform der -in ca.der -out ca.pem\nopenssl x509 -in ca.pem -noout -text","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Turn the startup panic into a clean config error before serving traffic\nuse std::panic::{catch_unwind, AssertUnwindSafe};\nlet acceptor = catch_unwind(AssertUnwindSafe(|| tls_settings.build()))\n    .map_err(|_| anyhow::anyhow!(\"invalid CA PEM for s2n listener: cannot parse ca.raw_pem\"))?;","preventionTips":["Validate every PEM before deploying: openssl x509 -in ca.pem -noout -text must succeed","Never pass .der files or hand-edited PEM text; generate with openssl and keep the file untouched","Add a startup self-test that builds the s2n acceptor (catch_unwind) so bad CA input fails the deploy, not traffic"],"tags":["rust","tls","s2n","pem","certificate","panic"],"backgroundTag":"invalid-pem-certificate","analyzedSha":"0046038bd402bc82912da862dadf9a479f31e9f1","analyzedAt":"2026-08-16T21:33:22.341Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}