diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-01 17:49:19 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-01 17:49:19 +0200 |
| commit | 6b38704d459dec1271c7ca883de3eb14190218f7 (patch) | |
| tree | 2fd1bd5c344092e4a115f3ab94e901517b3b6a03 /packages/meshbay-hub/src | |
| parent | 7d8c774e250b134222374f45726d5426714475de (diff) | |
| download | meshbay-6b38704d459dec1271c7ca883de3eb14190218f7.tar.gz | |
fix(hub): require user scope to add group members
Every mutating group endpoint depends on require_user_scope except
POST /v1/groups/{group_id}/members/{username}, which depended on
get_current_user — so a node-scoped daemon token (or a stolen one)
whose subject owns the group could add any existing user to it,
contradicting NS7 ("operator manages groups from the browser only").
test_node_auth.py::test_node_scope_blocks_add_member already existed
and was red on main; it passes now.
Third security review, finding M6.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pG75yGK3NthNfyjH74omG
Diffstat (limited to 'packages/meshbay-hub/src')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/api/groups.py | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/groups.py b/packages/meshbay-hub/src/meshbay_hub/api/groups.py index fdb0444..15c7a5d 100644 --- a/packages/meshbay-hub/src/meshbay_hub/api/groups.py +++ b/packages/meshbay-hub/src/meshbay_hub/api/groups.py @@ -586,9 +586,14 @@ async def update_group( async def add_group_member( group_id: str, username: str, - current_user: User = Depends(get_current_user), + current_user: User = Depends(require_user_scope), db: AsyncSession = Depends(get_db), ): + # `require_user_scope`, like every other mutating group endpoint: a + # node-scoped daemon token must not manage membership (NS7 — the operator + # manages groups from the browser). This was the one membership endpoint + # still on `get_current_user`, so a node token could add members to its + # operator's own groups. group = await db.get(Group, group_id) if not group: raise HTTPException(status_code=404, detail="Group not found") |