mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-07-17 17:32:27 -05:00
[PR #7397] Add custom role permissions: Manage Users, Groups, Policies #37074
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/dani-garcia/vaultwarden/pull/7397
Author: @tom27052006
Created: 7/1/2026
Status: 🔄 Open
Base:
main← Head:feature/custom-role-permissions📝 Commits (10+)
1f6d457Add custom role permissions: Manage Users, Groups, Policiesdf18711Silence struct_excessive_bools lint for Membership4d6b667Server-side collection/group permission hardening; works without web-vault changese72c97cHarden custom-role permissions: block indirect collection access via groups; block manage_users revoke/restore of admins; cargo fmt9f45aa7Fix privilege escalation: gate access_all in edit_member43fb19fHarden custom-role permission checks02b6c2cRestrict group reads to manage_groups and hide policy contents without manage_policies3b07e1eMerge remote-tracking branch 'upstream/main' into feature/custom-role-permissions1dcd3eaBlock collection access via group assignment in edit_member and send_invite81b76d9Persist manage_* permission flags on invite📊 Changes
15 files changed (+732 additions, -164 deletions)
View changed files
➕
migrations/mysql/2026-06-30-120000_add_custom_role_permissions/down.sql(+6 -0)➕
migrations/mysql/2026-06-30-120000_add_custom_role_permissions/up.sql(+9 -0)➕
migrations/postgresql/2026-06-30-120000_add_custom_role_permissions/down.sql(+6 -0)➕
migrations/postgresql/2026-06-30-120000_add_custom_role_permissions/up.sql(+9 -0)➕
migrations/sqlite/2026-06-30-120000_add_custom_role_permissions/down.sql(+6 -0)➕
migrations/sqlite/2026-06-30-120000_add_custom_role_permissions/up.sql(+9 -0)📝
src/api/admin.rs(+7 -0)📝
src/api/core/organizations.rs(+513 -111)📝
src/auth.rs(+83 -0)📝
src/db/models/collection.rs(+6 -5)📝
src/db/models/organization.rs(+62 -46)📝
src/db/schema.rs(+3 -0)📝
src/static/scripts/admin_users.js(+5 -1)📝
src/static/templates/admin/users.hbs(+3 -0)📝
src/static/templates/scss/vaultwarden.scss.hbs(+5 -1)📄 Description
Summary
This PR implements three granular custom-role permissions for organization members with the Custom role:
A member with the Custom role can be granted any combination of these three permissions. Each permission unlocks only its corresponding management actions (inviting/editing members, creating/editing groups, or editing policies) without granting access to collection contents.
Previously the Custom role was silently mapped to Manager and these permission checkboxes were hidden in the web vault because the server didn't support them.
This is a server-only change — it works with the standard, unmodified web-vault. (An earlier version of this PR required a web-vault patch; that is no longer necessary.)
Motivation
Currently, letting someone manage members or groups requires giving them an Admin role, which also grants visibility of every collection. This PR makes it possible to delegate specific administrative tasks without exposing collection contents — e.g. "this person may manage members, but must not see or manage collections".
Changes
manage_users,manage_groups,manage_policiesboolean columns tousers_organizations(sqlite / mysql / postgresql).MembershipType::Customis now a real, persisted variant instead of being downgraded to Manager. Its ordering stays at Manager level; elevated capabilities come solely from the explicit flags.ManageUsersHeaders,ManageGroupsHeaders,ManagePoliciesHeaders) that allow Admin/Owner or a Custom user with the matching flag.Security testing
I tested the introduced attack surface extensively via the API. Summary:
/syncreturn nothing for the org.Several real privilege-escalation issues were found and fixed during testing, all around collection access: a
manage_usersuser could originally grant themselves the other permissions, assign collections directly / in bulk / on invite, create collections, or grant collection access indirectly by assigning a member to a group that has collections. All are now blocked server-side.Read separation too: a group's collection assignments and member list are only readable by Admin/Owner or manage_groups members, and policy configuration only by Admin/Owner or manage_policies members — a member who only manages users cannot read group internals or policies.
This is thorough targeted testing of the changed surface, not a full audit. Permission systems are easy to get subtly wrong; a maintainer review of the permission checks would be very valuable, and there may be paths I haven't considered (e.g. interaction with SSO, emergency access, or concurrent requests).
Honest disclosure
Most of this work was done with the help of AI. I'm relatively new to the Vaultwarden codebase (and to Rust), so I can't claim to fully understand every implication on my own. Everything in the summary above I verified myself against a running instance — but I'd genuinely appreciate a careful review, and I'm happy to adjust or drop anything that doesn't fit the project's direction. If anything is unclear, just ask.
Notes
cargo clippy --features sqlitepasses cleanly.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.