{"record":{"id":"e8193e89e4fe1e4e","repo":"hyperledger/fabric","slug":"identity-index-out-of-range-requested-v-but-ide","errorCode":null,"errorMessage":"identity index out of range, requested %v, but identities length is %d","messagePattern":"identity index out of range, requested (.+?), but identities length is (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/cauthdsl/cauthdsl.go","lineNumber":63,"sourceCode":"\t\t\tfor _, policy := range policies {\n\t\t\t\tcopy(_used, used)\n\t\t\t\tif policy(signedData, _used) {\n\t\t\t\t\tverified++\n\t\t\t\t\tcopy(used, _used)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif verified >= t.NOutOf.N {\n\t\t\t\tcauthdslLogger.Debugf(\"%p gate %d evaluation succeeds\", signedData, grepKey)\n\t\t\t} else {\n\t\t\t\tcauthdslLogger.Debugf(\"%p gate %d evaluation fails\", signedData, grepKey)\n\t\t\t}\n\n\t\t\treturn verified >= t.NOutOf.N\n\t\t}, nil\n\tcase *cb.SignaturePolicy_SignedBy:\n\t\tif t.SignedBy < 0 || t.SignedBy >= int32(len(identities)) {\n\t\t\treturn nil, fmt.Errorf(\"identity index out of range, requested %v, but identities length is %d\", t.SignedBy, len(identities))\n\t\t}\n\t\tsignedByID := identities[t.SignedBy]\n\t\treturn func(signedData []msp.Identity, used []bool) bool {\n\t\t\tcauthdslLogger.Debugf(\"%p signed by %d principal evaluation starts (used %v)\", signedData, t.SignedBy, used)\n\t\t\tfor i, sd := range signedData {\n\t\t\t\tif used[i] {\n\t\t\t\t\tcauthdslLogger.Debugf(\"%p skipping identity %d because it has already been used\", signedData, i)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif cauthdslLogger.IsEnabledFor(zapcore.DebugLevel) {\n\t\t\t\t\t// Unlike most places, this is a huge print statement, and worth checking log level before create garbage\n\t\t\t\t\tcauthdslLogger.Debugf(\"%p processing identity %d - %v\", signedData, i, sd.GetIdentifier())\n\t\t\t\t}\n\t\t\t\terr := sd.SatisfiesPrincipal(signedByID)\n\t\t\t\tif err != nil {\n\t\t\t\t\tcauthdslLogger.Debugf(\"%p identity %d does not satisfy principal: %s\", signedData, i, err)\n\t\t\t\t\tcontinue\n\t\t\t\t}","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/cauthdsl/cauthdsl.go#L45-L81","documentation":"Thrown by the policy compiler in common/cauthdsl when a *cb.SignaturePolicy_SignedBy rule references an identity index that is negative or beyond the number of identities declared in the SignaturePolicyEnvelope. The compiler protects the subsequent identities[t.SignedBy] lookup from an out-of-range panic.","triggerScenarios":"Calling compile (directly or via provider.NewPolicy / EnvelopeBasedPolicyProvider.NewPolicy) with a SignaturePolicyEnvelope whose Rule contains SignedBy: N where N < 0 or N >= len(sigPolicy.Identities), e.g. after editing policy protobufs by hand or deserializing a truncated/corrupt policy.","commonSituations":"Hand-crafted or tool-generated channel application policies referencing principal indexes that were never added to the Identities list; policies serialized by newer tooling than the reader; byte-level corruption during storage or endorsement.","solutions":["Ensure every SignedBy index in the rule tree is within [0, len(Identities)-1] of the same envelope","Regenerate the policy from source (e.g. configtxgen / policygen tooling) instead of hand-editing serialized bytes","Log len(sigPolicy.Identities) and walk the rule tree before calling compile to find the offending index"],"exampleFix":"// before\nenv.Rule = &cb.SignaturePolicy{Type: &cb.SignaturePolicy_SignedBy{SignedBy: 3}} // only 2 identities\n// after\nenv.Identities = append(env.Identities, mspPrincipalForPeerOrg3)\nenv.Rule = &cb.SignaturePolicy{Type: &cb.SignaturePolicy_SignedBy{SignedBy: 2}} // index now valid","handlingStrategy":"validation","validationCode":"func validateSignedByIndexes(rule *cb.SignaturePolicy, ids []*msp.MSPPrincipal) error {\n    switch t := rule.GetType().(type) {\n    case *cb.SignaturePolicy_SignedBy:\n        if t.SignedBy < 0 || int(t.SignedBy) >= len(ids) {\n            return fmt.Errorf(\"SignedBy %d out of range for %d identities\", t.SignedBy, len(ids))\n        }\n    case *cb.SignaturePolicy_NOutOf_:\n        for _, r := range t.NOutOf.Rules {\n            if err := validateSignedByIndexes(r, ids); err != nil {\n                return err\n            }\n        }\n    }\n    return nil\n}","typeGuard":"func signedByInRange(rule *cb.SignaturePolicy, n int) bool {\n    sb, ok := rule.GetType().(*cb.SignaturePolicy_SignedBy)\n    return ok && sb.SignedBy >= 0 && int(sb.SignedBy) < n\n}","tryCatchPattern":null,"preventionTips":["Always build rules and the Identities list together from one source of truth","Walk the full nested rule tree, not just the top level, when validating indexes","Round-trip marshal/unmarshal the envelope and re-validate before persisting"],"tags":["policy","signature-policy","index-out-of-range"],"backgroundTag":"signature-policy-index-out-of-range","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"}