{"record":{"id":"2a4101bb161f9ed1","repo":"hashicorp/packer","slug":"signing-mode-q-requires-signer","errorCode":null,"errorMessage":"signing_mode %q requires signer","messagePattern":"signing_mode %q requires signer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/attestation/sign_key.go","lineNumber":37,"sourceCode":")\n\nfunc init() {\n\tRegisterSigner(SigningModeKey, newPEMSigner)\n}\n\ntype pemSigner struct {\n\tsigner   crypto.Signer\n\tverifier *pemVerifier\n}\n\ntype pemVerifier struct {\n\tpublicKey crypto.PublicKey\n\tkeyID     string\n}\n\nfunc newPEMSigner(_ context.Context, cfg BackendConfig) (Signer, error) {\n\tif cfg.SignerRef == \"\" {\n\t\treturn nil, fmt.Errorf(\"signing_mode %q requires signer\", SigningModeKey)\n\t}\n\n\tsigner, verifier, err := loadPEMSigner(cfg.SignerRef)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &pemSigner{signer: signer, verifier: verifier}, nil\n}\n\nfunc (s *pemSigner) Sign(_ context.Context, payloadType string, payload []byte) (Signature, error) {\n\tpae := PreAuthEncode(payloadType, payload)\n\n\tvar message []byte\n\tvar opts crypto.SignerOpts\n\tif _, ok := s.signer.Public().(ed25519.PublicKey); ok {\n\t\tmessage = pae\n\t\topts = crypto.Hash(0)","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/attestation/sign_key.go#L19-L55","documentation":"The PEM signing backend in internal/attestation/sign_key.go constructs its signer via newPEMSigner, which requires a BackendConfig.SignerRef pointing at a PEM-encoded private key file. When the 'key' signing mode is selected but no signer reference is supplied, the constructor immediately fails with this error. It is a configuration validation guard, thrown before any file I/O or key parsing occurs, so it always indicates a missing 'signer' setting rather than a bad key file.","triggerScenarios":"Calling code registers/enables signing mode SigningModeKey (\"key\") and invokes the signer factory newPEMSigner with a BackendConfig whose SignerRef field is the empty string — i.e. the signer path was never set.","commonSituations":"Users enable key-based attestation signing in a config file or flags but omit the signer/private-key path option; environment-driven config leaves the signer variable empty; a refactor renamed the config field so the value no longer populates SignerRef; code paths that programmatically build BackendConfig forget to assign SignerRef.","solutions":["Set the signer reference in your configuration: point cfg.SignerRef at a PEM file containing an RSA, ECDSA, or PKCS#8 private key (the same value used by loadPEMSigner to os.ReadFile the key).","Check the config-loading code path (flags, env vars, config file) that builds BackendConfig and confirm the signer option is actually parsed and assigned to SignerRef.","If signing is not intended, disable or unset the key signing mode so newPEMSigner is never invoked instead of leaving the mode enabled with no signer."],"exampleFix":"// before: enabling key signing without a signer\nattestation.SigningMode = \"key\"\n// signer path never provided -> error\n\n// after: supply the signer PEM path\nattestation.SigningMode = \"key\"\nattestation.SignerRef = \"/etc/packer/attest-signer.pem\" // RSA/ECDSA/PKCS#8 private key","handlingStrategy":"validation","validationCode":"if cfg.SignerRef == \"\" {\n\treturn fmt.Errorf(\"key signing mode requires a signer: set the signer PEM path before enabling signing mode %q\", attestation.SigningModeKey)\n}\nif _, err := os.Stat(cfg.SignerRef); err != nil {\n\treturn fmt.Errorf(\"signer %q unavailable: %w\", cfg.SignerRef, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate BackendConfig fields (especially SignerRef) as soon as config is parsed, before the signer factory runs.","Make the signer path a required config field with a clear error when the key signing mode is enabled without it.","Add a startup self-test that constructs the Signer eagerly so missing config fails fast at load time, not at first signature.","Document in the config schema which fields each signing mode requires."],"tags":["attestation","signing","configuration","missing-config"],"backgroundTag":"missing-required-config-option","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}