Admin authorization is npub-membership only — any admin can act on any key #60

Open
opened 2026-10-09 17:18:16 +00:00 by padreug · 0 comments
Owner

src/daemon/admin/validations/request-from-admin.ts:15-17 is the only gate for every admin RPC: hexpubkeys.includes(hexpubkey). No command checks that its target (keyName, policyId, keyUserId, tokenId) belongs to the caller. add_signing_condition.ts:33-43 writes an override for any keyUserId — and the override layer beats the policy in checkIfPubkeyAllowed step 3 — so admin A can grant {sign_event, all, allowed:true} on a KeyUser bound to admin B's key. create_new_token.ts:24 records createdBy but nothing reads it; revoke_user, revoke_token, update_policy, remove_policy_rule act on any id.

Impact: on a bunker with more than one admin npub, every admin is a full superuser over every key. Today our deployments configure a single admin npub (the lnbits instance), so this is a documented trust assumption rather than an exploitable gap — but it is the thing that stops us from ever adding a second admin or a third-party admin tool.

Fix direction: either (a) add an owner column on Key (admin pubkey) populated at create_new_key/create_account, and scope every command to keys the caller owns (joins through KeyUser → keyName and Token/Policy → keyName), or (b) pin single-tenant explicitly: refuse to start with more than one admin npub and say so in docs. (b) is a two-line change and honest about where we are.

Found during reforge run #1 (sandbox nsecbunkerd#20).

`src/daemon/admin/validations/request-from-admin.ts:15-17` is the only gate for every admin RPC: `hexpubkeys.includes(hexpubkey)`. No command checks that its target (`keyName`, `policyId`, `keyUserId`, `tokenId`) belongs to the caller. `add_signing_condition.ts:33-43` writes an override for any `keyUserId` — and the override layer beats the policy in `checkIfPubkeyAllowed` step 3 — so admin A can grant `{sign_event, all, allowed:true}` on a KeyUser bound to admin B's key. `create_new_token.ts:24` records `createdBy` but nothing reads it; `revoke_user`, `revoke_token`, `update_policy`, `remove_policy_rule` act on any id. Impact: on a bunker with more than one admin npub, every admin is a full superuser over every key. Today our deployments configure a single admin npub (the lnbits instance), so this is a documented trust assumption rather than an exploitable gap — but it is the thing that stops us from ever adding a second admin or a third-party admin tool. Fix direction: either (a) add an owner column on `Key` (admin pubkey) populated at `create_new_key`/`create_account`, and scope every command to keys the caller owns (joins through KeyUser → keyName and Token/Policy → keyName), or (b) pin single-tenant explicitly: refuse to start with more than one admin npub and say so in docs. (b) is a two-line change and honest about where we are. Found during reforge run #1 (sandbox nsecbunkerd#20).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/nsecbunkerd#60
No description provided.