{"record":{"id":"a35a95e6bba5a5b2","repo":"netbirdio/netbird","slug":"failed-to-verify-artifact-w","errorCode":null,"errorMessage":"failed to verify artifact: %w","messagePattern":"failed to verify artifact: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/artifactsign.go","lineNumber":51,"sourceCode":"\tLong: `Sign a software artifact (e.g., update bundle or binary) using the artifact's private key.\nThis command produces a detached signature that can be verified using the corresponding artifact public key.`,\n\tSilenceUsage: true,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tif err := handleSignArtifact(cmd, signArtifactPrivKeyFile, signArtifactArtifactFile); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to sign artifact: %w\", err)\n\t\t}\n\t\treturn nil\n\t},\n}\n\nvar verifyArtifactCmd = &cobra.Command{\n\tUse:          \"verify-artifact\",\n\tShort:        \"Verify an artifact signature using an artifact public key\",\n\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}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/artifactsign.go#L33-L69","documentation":"Generic wrapper from the verify-artifact RunE around handleVerifyArtifact. It wraps public key or bundle parsing, reading the artifact or signature file, signature decoding, or reposign.ValidateArtifact failures: future-dated or too-old signature timestamps, 'signing Key ... expired at', 'signature verification failed for Key ...', or 'no signing Key found with ID ...' when the key list does not contain the signer's key.","triggerScenarios":"Verifying with a public key set that lacks the key that produced the signature; system clock skew (future timestamp rejection); signature older than the accepted window; mismatched artifact/signature pair; expired artifact key at signature time.","commonSituations":"Rolling a signing key without publishing the new public key/bundle to verifiers; NTP drift on the verifying host; re-verification of old artifacts after the signing key expired.","solutions":["Read the chained ValidateArtifact message; 'no signing Key found with ID' means the verifier's key set is stale — distribute the new pub key or bundle","Fix clock sync if the message says the timestamp is in the future","Re-sign recent artifacts if the signature is rejected as too old or the key had expired at signing time","Confirm the artifact and .signature paths belong to the same build"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Publish the current signing pub key/bundle to verifiers before rotating\n// and assert the signature's KeyID exists in the verifier key set after each rotation","typeGuard":null,"tryCatchPattern":"err := verifyArtifactCmd.Execute()\nif err != nil {\n    msg := err.Error()\n    switch {\n    case strings.Contains(msg, \"no signing Key found with ID\"):\n        // verifier key set is stale: fetch the updated bundle\n    case strings.Contains(msg, \"timestamp is in the future\"):\n        // fix NTP on this host, then retry\n    case strings.Contains(msg, \"revoked\"), strings.Contains(msg, \"expired\"):\n        // reject the artifact: key revoked or expired at signing time\n    default:\n        return err\n    }\n}","preventionTips":["Distribute new public keys/bundles to all verifiers before signing with a new key","Keep NTP healthy on verifying machines","Re-sign artifacts after key rotation instead of shipping old signatures with new keys"],"tags":["cli","signing","verification","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}