{"record":{"id":"2e73e35a3296da43","repo":"netbirdio/netbird","slug":"failed-to-parse-artifact-public-key-w","errorCode":null,"errorMessage":"failed to parse artifact public key: %w","messagePattern":"failed to parse artifact public key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/artifactsign.go","lineNumber":170,"sourceCode":"\t}\n\n\tcmd.Printf(\"✅ Artifact signed successfully.\\n\")\n\tcmd.Printf(\"Signature file: %s\\n\", sigFile)\n\treturn nil\n}\n\nfunc handleVerifyArtifact(cmd *cobra.Command, pubKeyFile, artifactFile, signatureFile string) error {\n\tcmd.Println(\"🔍 Verifying artifact...\")\n\n\t// Read artifact public key\n\tpubKeyPEM, err := os.ReadFile(pubKeyFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read public key file: %w\", err)\n\t}\n\n\tpublicKey, err := reposign.ParseArtifactPubKey(pubKeyPEM)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse artifact public key: %w\", err)\n\t}\n\n\t// Read artifact data\n\tartifactData, err := os.ReadFile(artifactFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read artifact file: %w\", err)\n\t}\n\n\t// Read signature\n\tsigBytes, err := os.ReadFile(signatureFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read signature file: %w\", err)\n\t}\n\n\tsignature, err := reposign.ParseSignature(sigBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse signature: %w\", err)\n\t}","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/artifactsign.go#L152-L188","documentation":"reposign.ParseArtifactPubKey failed in verify-artifact. It pem.Decodes the input and requires block type \"ARTIFACT PUBLIC KEY\" with a JSON body containing a 32-byte Ed25519 public key (reposign/key.go:99-124). Wrong PEM type (e.g. a root public key or the private key file), undecodable PEM, corrupt JSON, or wrong key length all fail. Note it parses only the first block; extra concatenated keys are silently ignored.","triggerScenarios":"Passing the ROOT PUBLIC KEY file to --artifact-public-key-file; passing the artifact private key PEM; passing a standard OpenSSH/PEM public key; a bundle whose first block is corrupt.","commonSituations":"Key naming confusion in the release vault (root vs artifact, public vs private); reusing an openssl-generated key instead of the one from generate-artifact-key.","solutions":["Use the public half produced by `signer generate-artifact-key` (-----BEGIN ARTIFACT PUBLIC KEY-----)","Check you did not pass the root key or a private key: head -1 <file> must read -----BEGIN ARTIFACT PUBLIC KEY-----","If verifying against a bundle, confirm the first PEM block is an artifact public key"],"exampleFix":"// before\n./signer verify-artifact --artifact-public-key-file root-key-pub.pem ...\n\n// after\n./signer verify-artifact --artifact-public-key-file artifact-key-pub.pem ...","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isArtifactPublicKeyPEM(data []byte) bool {\n    block, _ := pem.Decode(data)\n    return block != nil && block.Type == \"ARTIFACT PUBLIC KEY\"\n}","tryCatchPattern":null,"preventionTips":["Keep root and artifact public keys in differently named files and verify the PEM tag before use","Verify against the root-signed bundle from the key store rather than ad-hoc copies"],"tags":["go","crypto","ed25519","pem","release-signing"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}