{"record":{"id":"a89b57b1c1b5e23c","repo":"caddyserver/caddy","slug":"access-control-d-public-key-d-parsing-base64-ce","errorCode":null,"errorMessage":"access control %d public key %d: parsing base64 certificate DER: %v","messagePattern":"access control (.+?) public key (.+?): parsing base64 certificate DER: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"admin.go","lineNumber":552,"sourceCode":"\tif err != nil {\n\t\treturn err\n\t}\n\n\t// make the HTTP handler but disable Host/Origin enforcement\n\t// because we are using TLS authentication instead\n\thandler, err := cfg.Admin.newAdminHandler(addr, true, ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// create client certificate pool for TLS mutual auth, and extract public keys\n\t// so that we can enforce access controls at the application layer\n\tclientCertPool := x509.NewCertPool()\n\tfor i, accessControl := range cfg.Admin.Remote.AccessControl {\n\t\tfor j, certBase64 := range accessControl.PublicKeys {\n\t\t\tcert, err := decodeBase64DERCert(certBase64)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"access control %d public key %d: parsing base64 certificate DER: %v\", i, j, err)\n\t\t\t}\n\t\t\taccessControl.publicKeys = append(accessControl.publicKeys, cert.PublicKey)\n\t\t\tclientCertPool.AddCert(cert)\n\t\t}\n\t}\n\n\t// create TLS config that will enforce mutual authentication\n\tif identityCertCache == nil {\n\t\treturn fmt.Errorf(\"cannot enable remote admin without a certificate cache; configure identity management to initialize a certificate cache\")\n\t}\n\tcmCfg := cfg.Admin.Identity.certmagicConfig(remoteLogger, false)\n\ttlsConfig := cmCfg.TLSConfig()\n\ttlsConfig.NextProtos = nil // this server does not solve ACME challenges\n\ttlsConfig.ClientAuth = tls.RequireAndVerifyClientCert\n\ttlsConfig.ClientCAs = clientCertPool\n\n\t// convert logger to stdlib so it can be used by HTTP server\n\tserverLogger, err := zap.NewStdLogAt(remoteLogger, zap.DebugLevel)","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/admin.go#L534-L570","documentation":"When enabling the remote admin endpoint, Caddy decodes each base64-DER client certificate listed under admin.remote.access_control[].public_keys to build the client CA pool. If any entry is not valid base64 or not a parseable DER certificate, this error reports which access control (i) and key (j) failed, wrapping the x509/base64 cause.","triggerScenarios":"admin.remote config where a public_keys entry is base64 of PEM instead of DER; truncated or whitespace-mangled base64; a certificate encoded with standard base64 including '=' padding the decoder rejects, or simply not a certificate at all.","commonSituations":"Converting a PEM client cert to base64 without first converting to DER (base64 of the PEM text); copy-paste truncation; exporting the public key bytes instead of the full certificate; line-wrapped base64 pasted with newlines.","solutions":["Produce the correct value: openssl x509 -in client.pem -outform DER | base64 -w0","Check the indicated indices (access control %d, public key %d) in your config against the error to find the exact bad entry","Remove whitespace/newlines from the base64 string","Verify the DER parses: openssl x509 -inform DER -in client.der -noout"],"exampleFix":"# before: base64 of PEM text (wrong)\npublic_keys: [\"LS0tLS1CRUdJTiBDRVJUSUZ...\"]\n\n# after: base64 of DER bytes\nopenssl x509 -in client.pem -outform DER | base64 -w0\npublic_keys: [\"MIIBvzCCAYWgAwIBAgIU...\"]","handlingStrategy":"validation","validationCode":"func toBase64DER(pemCert []byte) (string, error) {\n\tblock, _ := pem.Decode(pemCert)\n\tif block == nil {\n\t\treturn \"\", errors.New(\"input is not PEM\")\n\t}\n\tif _, err := x509.ParseCertificate(block.Bytes); err != nil {\n\t\treturn \"\", fmt.Errorf(\"not a certificate: %v\", err)\n\t}\n\treturn base64.StdEncoding.EncodeToString(block.Bytes), nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate values only with openssl x509 -outform DER | base64 -w0","Never base64 the PEM text itself","Write a config-rendering test that decodes every public_keys entry and parses it as DER"],"tags":["admin-api","remote-admin","certificates","base64","configuration"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}