{"record":{"id":"2a0acbc525ec11bf","repo":"hyperledger/fabric","slug":"pkiid-is-nil","errorCode":null,"errorMessage":"PKIID is nil","messagePattern":"PKIID is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/identity/identity.go","lineNumber":105,"sourceCode":"func (is *identityMapperImpl) periodicalPurgeUnusedIdentities() {\n\tusageTh := GetIdentityUsageThreshold()\n\tfor {\n\t\tselect {\n\t\tcase <-is.stopChan:\n\t\t\treturn\n\t\tcase <-time.After(usageTh / 10):\n\t\t\tis.SuspectPeers(func(_ api.PeerIdentityType) bool {\n\t\t\t\treturn false\n\t\t\t})\n\t\t}\n\t}\n}\n\n// put associates an identity to its given pkiID, and returns an error\n// in case the given pkiID doesn't match the identity\nfunc (is *identityMapperImpl) Put(pkiID common.PKIidType, identity api.PeerIdentityType) error {\n\tif pkiID == nil {\n\t\treturn errors.New(\"PKIID is nil\")\n\t}\n\tif identity == nil {\n\t\treturn errors.New(\"identity is nil\")\n\t}\n\n\texpirationDate, err := is.mcs.Expiration(identity)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed classifying identity\")\n\t}\n\n\tif err := is.mcs.ValidateIdentity(identity); err != nil {\n\t\treturn err\n\t}\n\n\tid := is.mcs.GetPKIidOfCert(identity)\n\tif !bytes.Equal(pkiID, id) {\n\t\treturn errors.New(\"identity doesn't match the computed pkiID\")\n\t}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/identity/identity.go#L87-L123","documentation":"identityMapperImpl.Put registers an identity keyed by its PKI-ID. It rejects a nil pkiID outright because the whole map is keyed on PKI-IDs; storing under a nil key would corrupt identity lookups and later cryptographic checks.","triggerScenarios":"Calling Put (from NewIdentityMapper's store population or application code) with pkiID = nil, typically when the caller obtained the PKI-ID from a malformed message or empty identity field.","commonSituations":"Processing gossip messages with missing/zeroed pki-id fields; tests stubbing identity mapper inputs; deserialization failures that leave PKIidType as an empty/nil byte slice.","solutions":["Ensure the PKI-ID is extracted correctly (mcs.GetPKIidOfCert(identity)) before calling Put and is non-empty","Reject/drop upstream messages whose pki-id field is empty instead of forwarding them to the identity store","Add a caller-side check len(pkiID) > 0 before invoking Put"],"exampleFix":"// before\nmapper.Put(msg.Nonce, identity) // pkiID may be nil\n\n// after\npkiID := mapper.mcs.GetPKIidOfCert(identity)\nif len(pkiID) == 0 {\n    return errors.New(\"empty pkiID\")\n}\nmapper.Put(pkiID, identity)","handlingStrategy":"validation","validationCode":"if len(pkiID) == 0 {\n    return errors.New(\"refusing to put identity with nil/empty pkiID\")\n}\nerr := mapper.Put(pkiID, identity)","typeGuard":"func validPkiID(p common.PKIidType) bool { return len(p) > 0 }","tryCatchPattern":"if err := mapper.Put(pkiID, identity); err != nil && err.Error() == \"PKIID is nil\" {\n    logger.Warning(\"dropping identity with nil pkiID\")\n    return\n}","preventionTips":["Always derive pkiID from the certificate or message fields and check non-empty before Put","Drop gossip messages with empty pki-id fields at the parsing layer","Add unit tests covering nil-pkiID inputs to identity registration"],"tags":["gossip","hyperledger-fabric","identity"],"backgroundTag":"nil-identifier","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}