Jun 24, 2026·5 min read·4 visits
Authenticated users with 'users.edit' can modify their own accounts via the API to self-grant arbitrary permissions, excluding global admin/superuser roles.
A privilege escalation vulnerability in Snipe-IT versions prior to 8.6.0 allows authenticated users with profile-editing capabilities to elevate their own permissions by performing a PATCH request on their own user endpoint.
Snipe-IT is an open-source IT asset management system designed to track hardware, software licenses, and users. Within its authorization architecture, granular permissions dictate which actions users can take, such as creating assets, checking out licenses, or viewing reports. This vulnerability exists within the user-management boundary.\n\nUnder vulnerable configurations, any authenticated user possessing the 'users.edit' permission and API access can manipulate their own permissions. By issuing an authorized update request to their own user profile endpoint, they circumvent intended authorization controls.\n\nThe flaw is classified under CWE-863 (Incorrect Authorization). Although the system implements access control checks, it fails to enforce restrictions when the target of a profile-editing action matches the identity of the requester. This allows lateral and vertical privilege escalation up to almost all non-administrative privileges.
The core weakness resides within the logic implemented in PreserveUnauthorizedPrivilegedPermissionsAction::run(). This action class acts as a filter to ensure that users do not grant permissions they themselves do not possess or are not authorized to assign. In vulnerable versions, this function accepted $requestedPermissions, $authenticatedUser, and $originalPermissions as inputs.\n\nWhile the logic successfully prevented non-superusers from assigning the global admin or superuser roles, it did not differentiate between editing another user and editing oneself. If a user possessed the generic users.edit capability, they were permitted to make modifications to user profiles.\n\nBecause the endpoint allowed a user to direct edit actions to their own profile identifier (/api/v1/users/{id}), the application ran the validation sequence against the user's own profile. Due to the lack of target context inside PreserveUnauthorizedPrivilegedPermissionsAction, the application accepted the payload, effectively letting the user self-authorize higher-level application access.
To fix this vulnerability, the development team modified the signature and logic of PreserveUnauthorizedPrivilegedPermissionsAction::run(). The function now accepts a fourth nullable parameter: ?User $targetUser = null. This parameter provides the context of which specific database record is being modified.\n\nA conditional branch was introduced at the beginning of the run method. If a target user object is provided, the authenticated user is not a superuser, and the authenticated user's ID matches the target user's ID, the function immediately discards the request. It returns the pre-existing, unmodified permissions array, effectively preventing self-modification.\n\nBelow is the core logic fix demonstrating the target validation block:\n\nphp\n// Patched logic in app/Actions/Permissions/PreserveUnauthorizedPrivilegedPermissionsAction.php\npublic static function run(array $requestedPermissions, User $authenticatedUser, array $originalPermissions = [], ?User $targetUser = null): array\n{\n // Disallow non-admin/superuser users from modifying their own permissions\n if ($targetUser && !$authenticatedUser->isSuperUser() && $authenticatedUser->id === $targetUser->id) {\n return $originalPermissions;\n }\n // ... standard validation checks continue below\n}\n\n\nIn addition, the controller classes (app/Http/Controllers/Api/UsersController.php and app/Http/Controllers/Users/UsersController.php) were updated to forward the target user ($user) during the profile update flow. This ensures the action class has the required context to prevent self-escalation regardless of whether the request originates from the API or the web UI.
Exploitation of this vulnerability requires an established user session or a Personal Access Token with API and users.edit permissions. The attacker first resolves their own user identifier by calling the active user endpoint. Once the identifier is obtained, they construct a crafted payload targeting their own user record.\n\nThe attacker issues a standard HTTP PATCH request to the /api/v1/users/{id} endpoint. The payload contains a permissions object setting target privileges to "1" (enabled). For example, the attacker can enable permissions such as assets.create, licenses.edit, and reports.view.\n\nBelow is the data flow representing how the input is handled across the vulnerable boundaries:\n\nmermaid\ngraph LR\n Attacker["Attacker (users.edit)"] -->|PATCH /api/v1/users/self| API["Api/UsersController"]\n API -->|Validates session/token| Action["PreserveUnauthorizedPrivilegedPermissionsAction"]\n Action -->|Checks for admin/superuser only| DB["Database Save"]\n DB -->|Saves escalated permissions| Attacker\n\n\nBecause the vulnerability does not require complex heap shaping, timing, or external dependencies, exploitation is highly reliable. Any endpoint interaction that bypasses the frontend validation and directly calls the API controller will successfully store the escalated privileges in the database.
The impact of successful exploitation is a complete compromise of the authorization model within the affected Snipe-IT instance. An attacker can elevate their privileges to encompass almost all non-administrative operational roles. This includes full read, write, update, and delete access across assets, accessories, components, and licenses.\n\nWith elevated access, an attacker can exfiltrate sensitive corporate asset logs, modify system databases to mask physical theft, or alter user assignments. However, because the vulnerability explicitly blocks the assignment of the global admin and superuser roles, the attacker cannot access core administrative panel settings.\n\nThis restriction maintains the CVSS base score at 5.5, indicating a moderate impact. Nevertheless, in environments where Snipe-IT handles critical enterprise logistics or active asset inventories, this vulnerability poses a significant insider threat risk.
The primary and most effective remediation is upgrading Snipe-IT to version 8.6.0 or higher. This release contains the complete validation fix across both the API and UI routes. Administrators should verify their deployments and execute standard upgrade procedures immediately.\n\nIn environments where an immediate upgrade is not feasible, administrators must implement workarounds. The most effective tactical mitigation is to audit all active user permissions and temporarily revoke users.edit and API access from any account that does not strictly require administrative capabilities.\n\nAdditionally, monitoring web server access logs for suspicious activity is advised. Security teams should query for HTTP PATCH requests targeting /api/v1/users/ where the requesting user's identity matches the URL parameter, followed by database validation to confirm whether unauthorized permission states exist.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Snipe-IT Grokability | < 8.6.0 | 8.6.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-863 |
| Attack Vector | Network |
| CVSS Score | 5.5 |
| EPSS Score | Not Indexed |
| Impact | Privilege Escalation |
| Exploit Status | poc |
| KEV Status | Not Listed |
The software performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly prove that the actor is authorized to perform that action or access that resource.
An observable timing discrepancy vulnerability (CWE-208) in Filament's administrative login page allows unauthenticated remote attackers to determine the existence of registered email addresses. This timing side-channel arises from short-circuiting logic that skips expensive password hashing checks when a queried email address is not found in the database. Attackers can execute statistical timing attacks to map active administrator accounts, facilitating subsequent targeted brute-force or credential-stuffing campaigns.
Filament's ImageColumn (used in tables) and ImageEntry (used in infolists) components render database values inside HTML attributes without validation or sanitization. This allows an attacker to inject arbitrary HTML attributes, leading to Stored Cross-Site Scripting (XSS).
The Netty incubator codec for Oblivious HTTP (OHTTP) fails to verify that a cryptographically signed final chunk is received before the outer HTTP body terminates. This missing validation allows an on-path adversary to truncate chunked-OHTTP messages cleanly at a non-final chunk boundary, leading to undetected data truncation and compromising message integrity. The vulnerability affects multiple versions of the maven package io.netty.incubator:netty-incubator-codec-ohttp prior to 0.0.22.Final.
Prior to version 4.1.4, phpMyFAQ used the cryptographically broken SHA-1 algorithm to hash custom attachment encryption keys stored in the database. Attackers with database access can recover these plaintext keys through offline brute-force attacks and subsequently decrypt sensitive file attachments.
CVE-2026-48500 is an authorization bypass vulnerability within Filament, a full-stack Laravel administration panel suite. The flaw arises from the unauthenticated exposure of Livewire's file upload RPC endpoints on guest-facing pages, allowing remote actors to upload arbitrary files to temporary storage, potentially leading to storage exhaustion and service disruption.
A UNIX symbolic link following vulnerability exists in the provider cache installation mechanism of OpenTofu. This flaw allows an attacker with control over the repository files to write files outside of the intended workspace boundary during initialization.