GitHub Security Advisory: GHSA-h4hq-rgvh-wh27
Package: vaultwarden (RUST)
Severity: HIGH (CVSS 8.3)
CWE: CWE-269: Improper Privilege Management, CWE-285: Improper Authorization, CWE-863: Incorrect Authorization
Vulnerable versions: <= 1.35.3
Patched in: 1.35.4

Summary: Vaultwarden's Collection Management Operations Allowed Without `manage` Verification for Manager Role

Details:
## Summary

Testing confirmed that even when a Manager has `manage=false` for a given collection, they can still perform the following management operations as long as they have access to the collection:

* `PUT /api/organizations/<org_id>/collections/<col_id>` succeeds (HTTP 200)
* `PUT /api/organizations/<org_id>/collections/<col_id>/users` succeeds (HTTP 200)
* `DELETE /api/organizations/<org_id>/collections/<col_id>` succeeds (HTTP 200)



## Description

* The Manager guard checks only whether the user **can access the collection**, not whether they have `manage` privileges. This check is directly applied to management endpoints.
src/auth.rs:816
  ```rust

  if !Collection::can_access_collection(&headers.membership, &col_id, &conn).await {
      err_handler!("The current user isn't a manager for this collection")
  }
  ```

* The `can_access_collection` function does **not** evaluate the `manage` flag.
  src/db/models/collection.rs:140

  ```rust

  pub async fn can_access_collection(member: &Membership, col_id: &CollectionId, conn: &DbConn) -> bool {
      member.has_status(MembershipStatus::Confirmed)
          && (member.has_full_access()
              || CollectionUser::has_access_to_collection_by_user(col_id, &member.user_uuid, conn).await
              || ...
  ```

* A separate management-permission check exists and includes `manage` validation, but it is **not used** during authorization for the affected endpoints.
  src/db/models/collection.rs:516

  ```rust

  pub async fn is_manageable_by_user(&self, user_uuid: &UserId, conn: &DbConn) -> bool {
      let Some(member) = Membership::find_confirmed_by_user_and_org(user_uuid, &self.org_uuid, conn).await else {
          return false;
      };
      if member.has_full_access() {
          return true;
      }
      ...
  ```

* The actual update and deletion endpoints only accept `ManagerHeaders` and do not perform additional `manage` checks.
  src/api/core/organizations.rs:608

```rust
  async fn put_organization_collection_update(..., headers: ManagerHeaders, ...)
```

  src/api/core/organizations.rs:890

```rust
  async fn put_collection_users(..., headers: ManagerHeaders, ...)
```
  

src/api/core/organizations.rs:747

```rust
  async fn delete_organization_collection(..., headers: ManagerHeaders, ...)
  ```



## Preconditions

* The attacker is a **Manager** within the target organization.
* The attacker has access to the target collection (`assigned=true`).
* The attacker’s permission for that collection is `manage=false`.
* A valid API access token has been obtained.



## Steps to Reproduce

1. Confirm that the attacker’s current permissions for the target collection include `manage=false`.
<img width="2015" height="636" alt="image" src="https://github.com/user-attachments/assets/58ddc733-e37c-4766-a980-b1ea1918ceb4" />

2. As a control test, verify that update operations fail for collections the attacker cannot access.
<img width="2021" height="852" alt="image" src="https://g