{"record":{"id":"8cb78130485c52db","repo":"netbirdio/netbird","slug":"failed-to-verify-artifact-key-w","errorCode":null,"errorMessage":"failed to verify artifact key: %w","messagePattern":"failed to verify artifact key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/artifactsign.go","lineNumber":65,"sourceCode":"\tLong:         `Verify a software artifact signature using the artifact's public key.`,\n\tSilenceUsage: true,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif err := handleVerifyArtifact(cmd, verifyArtifactPubKeyFile, verifyArtifactFile, verifyArtifactSignatureFile); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to verify artifact: %w\", err)\n\t\t}\n\t\treturn nil\n\t},\n}\n\nvar verifyArtifactKeyCmd = &cobra.Command{\n\tUse:   \"verify-artifact-key\",\n\tShort: \"Verify an artifact public key was signed by a root key\",\n\tLong: `Verify that an artifact public key (or bundle) was properly signed by a root key.\nThis validates the chain of trust from the root key to the artifact key.`,\n\tSilenceUsage: true,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif err := handleVerifyArtifactKey(cmd, verifyArtifactKeyPubKeyFile, verifyArtifactKeyRootPubKeyFile, verifyArtifactKeySignatureFile, verifyArtifactKeyRevocationFile); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to verify artifact key: %w\", err)\n\t\t}\n\t\treturn nil\n\t},\n}\n\nfunc init() {\n\trootCmd.AddCommand(signArtifactCmd)\n\trootCmd.AddCommand(verifyArtifactCmd)\n\trootCmd.AddCommand(verifyArtifactKeyCmd)\n\n\tsignArtifactCmd.Flags().StringVar(&signArtifactPrivKeyFile, \"artifact-key-file\", \"\", fmt.Sprintf(\"Path to the artifact private key file used for signing (or set %s env var)\", envArtifactPrivateKey))\n\tsignArtifactCmd.Flags().StringVar(&signArtifactArtifactFile, \"artifact-file\", \"\", \"Path to the artifact to be signed\")\n\n\t// artifact-file is required, but artifact-key-file can come from env var\n\tif err := signArtifactCmd.MarkFlagRequired(\"artifact-file\"); err != nil {\n\t\tpanic(fmt.Errorf(\"mark artifact-file as required: %w\", err))\n\t}\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/artifactsign.go#L47-L83","documentation":"Generic wrapper from the verify-artifact-key RunE around handleVerifyArtifactKey, which validates the chain of trust from a root public key to an artifact key (or key bundle). It wraps root public key parsing, artifact key/bundle parsing, signature reading/decoding, and ValidateArtifactKeys failures such as 'failed to verify signature of artifact keys' or 'all N artifact keys are revoked' when a revocation list is supplied.","triggerScenarios":"Verifying an artifact key signed by a different root; a tampered key or bundle; a revoked key set checked against a revocation list; supplying the wrong .sig file; key/bundle that fails PEM or key-size checks.","commonSituations":"Root key rotation where old artifact keys are checked against the new root; distributing a key bundle signed by a stale root; passing a revocation list from a newer rotation than the keys being verified.","solutions":["Match the root public key with the root that actually signed the artifact key (check provenance of both)","If 'all artifact keys are revoked', mint new artifact keys or verify without superseded keys","Confirm the signature file is the one produced alongside the key/bundle","After root rotation, re-bundle artifact keys with the new root before verification"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// After any root rotation, verify old artifact keys against the old root once,\n// then re-bundle them under the new root before wide distribution","typeGuard":null,"tryCatchPattern":"err := verifyArtifactKeyCmd.Execute()\nif err != nil {\n    msg := err.Error()\n    switch {\n    case strings.Contains(msg, \"failed to verify signature\"):\n        // trust break: key not signed by this root — do not trust the key\n    case strings.Contains(msg, \"revoked\"):\n        // key set revoked: obtain freshly issued artifact keys\n    default:\n        return err\n    }\n}","preventionTips":["Record which root signed each artifact key during issuance","Re-bundle artifact keys under a new root as part of every rotation runbook","Verify the root-key-to-artifact-key chain in CI before publishing keys to verifiers"],"tags":["cli","signing","verification","chain-of-trust","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}