{"record":{"id":"6b139cda05b0840f","repo":"hashicorp/terraform","slug":"failed-to-parse-certificate-q-s","errorCode":null,"errorMessage":"failed to parse certificate %q: %s","messagePattern":"failed to parse certificate %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/provisioner.go","lineNumber":405,"sourceCode":"\t}\n\n\tif opts.sshAgent != nil {\n\t\tconf.Auth = append(conf.Auth, opts.sshAgent.Auth())\n\t}\n\n\treturn conf, nil\n}\n\n// Create a Cert Signer and return ssh.AuthMethod\nfunc signCertWithPrivateKey(pk string, certificate string) (ssh.AuthMethod, error) {\n\trawPk, err := ssh.ParseRawPrivateKey([]byte(pk))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse private key %q: %s\", pk, err)\n\t}\n\n\tpcert, _, _, _, err := ssh.ParseAuthorizedKey([]byte(certificate))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse certificate %q: %s\", certificate, err)\n\t}\n\n\tusigner, err := ssh.NewSignerFromKey(rawPk)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create signer from raw private key %q: %s\", rawPk, err)\n\t}\n\n\tucertSigner, err := ssh.NewCertSigner(pcert.(*ssh.Certificate), usigner)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create cert signer %q: %s\", usigner, err)\n\t}\n\n\treturn ssh.PublicKeys(ucertSigner), nil\n}\n\nfunc readPrivateKey(pk string) (ssh.AuthMethod, error) {\n\t// We parse the private key on our own first so that we can\n\t// show a nicer error if the private key has a password.","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/communicator/ssh/provisioner.go#L387-L423","documentation":"In signCertWithPrivateKey, after parsing the private key, the certificate string is parsed via ssh.ParseAuthorizedKey. If the certificate is not a valid SSH authorized key / certificate format, parsing fails. SECURITY NOTE: the error message interpolates the full certificate material via %q.","triggerScenarios":"Providing a certificate value to the SSH connection that is not a valid SSH certificate. Triggered by: providing a regular public key instead of a certificate (missing -cert.pub), a corrupt or truncated certificate string, a certificate in an unsupported format, or certificate text with mangled whitespace/newlines.","commonSituations":"User references id_rsa.pub (the public key) instead of id_rsa-cert.pub (the actual certificate). Certificate was copied with line breaks inserted by a terminal or secrets manager. Certificate generated by a CA in an incompatible format. Using a host certificate where a user certificate is expected.","solutions":["Verify you are providing an SSH certificate (filename typically ends in -cert.pub), not a plain public key.","Ensure the certificate string is complete and untruncated — it should be a single line starting with the key type (e.g., ssh-rsa-cert-v01@openssh.com).","Check for whitespace/newline corruption if loading from a secrets manager or environment variable.","Regenerate the certificate from the CA if it may be corrupt: ssh-keygen -s ca_key -I identity id_rsa.pub."],"exampleFix":"# before — using plain public key instead of certificate\nconnection {\n  certificate  = file(\"~/.ssh/id_rsa.pub\")  # wrong file\n  private_key = file(\"~/.ssh/id_rsa\")\n}\n\n# after — using the actual signed certificate\nconnection {\n  certificate  = file(\"~/.ssh/id_rsa-cert.pub\")\n  private_key = file(\"~/.ssh/id_rsa\")\n}","handlingStrategy":"validation","validationCode":"// Pre-validate the certificate is a valid SSH certificate (not just a public key)\nimport \"golang.org/x/crypto/ssh\"\n\nfunc validateSSHCertificate(cert string) error {\n    key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(cert))\n    if err != nil {\n        return fmt.Errorf(\"certificate not parseable: %w\", err)\n    }\n    sshCert, ok := key.(*ssh.Certificate)\n    if !ok {\n        return errors.New(\"provided value is a public key, not a certificate\")\n    }\n    _ = sshCert\n    return nil\n}","typeGuard":"func isSSHCertificate(cert string) bool {\n    key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(cert))\n    if err != nil {\n        return false\n    }\n    _, ok := key.(*ssh.Certificate)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Always reference -cert.pub files for certificates, not .pub files.","Verify certificates with ssh-keygen -L -f <cert-file> before use.","Ensure certificate and key come from the same key pair.","Avoid logging certificate material in error output."],"tags":["ssh","crypto","certificate","host-key"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}