Severity: High — confidentiality bypass (unauthorized read of restricted storage program data).
Where: branch fix/storage-rpc-and-health-stabilisation (the storage RPC read layer; not yet on testnet).
Summary: Reads of a restricted storage program are authorized against an unsigned, caller-supplied requesterAddress string. Any anonymous caller who names an allowlisted address reads the confidential data. Program data is stored plaintext, so the ACL is the only confidentiality barrier. Writes are unaffected — they derive the sender from a verified signed transaction.
Read path:
nodeCall src/libs/network/rpcDispatch.ts:124
manageNodeCall src/libs/network/manageNodeCall.ts:18-29 — passes request data verbatim, no signature check
getStorageProgram handler src/libs/network/handlers/storageProgramHandlers.ts:22
- routine
src/libs/network/routines/nodecalls/getStorageProgram.ts:29 — takes data.requesterAddress as a plain string
getAccessibleProgram src/libs/network/routines/nodecalls/storageProgramShared.ts:129
checkReadPermission src/libs/blockchain/gcr/gcr_routines/GCRStorageProgramRoutines.ts:1115-1179 — owner/acl.allowed/group string matching, no signature/nonce/key-ownership proof. (DB mirror: readReachablePredicate ~942-1005.)
Impact: any party who learns or guesses an allowlisted address reads all restricted program data via a single unauthenticated RPC call.
Fix direction: require a verified signature binding requesterAddress to a real key (signature over storageAddress + timestamp/nonce), verified before the ACL check in the read path; public-mode reads stay open. The SDK query methods (currently "no authentication required") will need a matching follow-up change.
Note: could not reproduce against the live node (demosnode.discus.sh egress blocked from this environment); confirmed from source, not the deployed commit.
Reported by Random block via Slack.
Severity: High — confidentiality bypass (unauthorized read of restricted storage program data).
Where: branch
fix/storage-rpc-and-health-stabilisation(the storage RPC read layer; not yet ontestnet).Summary: Reads of a
restrictedstorage program are authorized against an unsigned, caller-suppliedrequesterAddressstring. Any anonymous caller who names an allowlisted address reads the confidential data. Program data is stored plaintext, so the ACL is the only confidentiality barrier. Writes are unaffected — they derive the sender from a verified signed transaction.Read path:
nodeCallsrc/libs/network/rpcDispatch.ts:124manageNodeCallsrc/libs/network/manageNodeCall.ts:18-29— passes requestdataverbatim, no signature checkgetStorageProgramhandlersrc/libs/network/handlers/storageProgramHandlers.ts:22src/libs/network/routines/nodecalls/getStorageProgram.ts:29— takesdata.requesterAddressas a plain stringgetAccessibleProgramsrc/libs/network/routines/nodecalls/storageProgramShared.ts:129checkReadPermissionsrc/libs/blockchain/gcr/gcr_routines/GCRStorageProgramRoutines.ts:1115-1179— owner/acl.allowed/group string matching, no signature/nonce/key-ownership proof. (DB mirror:readReachablePredicate~942-1005.)Impact: any party who learns or guesses an allowlisted address reads all restricted program data via a single unauthenticated RPC call.
Fix direction: require a verified signature binding
requesterAddressto a real key (signature over storageAddress + timestamp/nonce), verified before the ACL check in the read path; public-mode reads stay open. The SDK query methods (currently "no authentication required") will need a matching follow-up change.Note: could not reproduce against the live node (
demosnode.discus.shegress blocked from this environment); confirmed from source, not the deployed commit.Reported by Random block via Slack.