CVE-2026-55694 Overview
Snipe-IT is an open-source IT asset and license management system used by organizations to track hardware, software, and user acknowledgements. CVE-2026-55694 is an authorization flaw [CWE-639] in Snipe-IT versions prior to 8.6.3. A restricted authenticated user can query /api/v1/users/{target_id}/eulas to retrieve another user's randomized End-User License Agreement (EULA) filename. The attacker can then download the signed file through /account/stored-eula-file/{filename}. The controllers app/Http/Controllers/ProfileController.php and app/Http/Controllers/Api/UsersController.php failed to enforce ownership and target-user authorization consistently.
Critical Impact
Any low-privileged authenticated user can enumerate and download other users' signed EULA files, exposing personally identifiable acknowledgement records stored in Snipe-IT.
Affected Products
- Snipe-IT versions prior to 8.6.3
- app/Http/Controllers/Api/UsersController.php (EULAs endpoint)
- app/Http/Controllers/ProfileController.php (stored EULA file route)
Discovery Timeline
- 2026-08-19 - CVE-2026-55694 published to NVD
- 2026-08-19 - Last updated in NVD database
- v8.6.3 - Grokability releases Snipe-IT patch tightening EULA download authorization
Technical Details for CVE-2026-55694
Vulnerability Analysis
The vulnerability is an Insecure Direct Object Reference (IDOR) affecting two distinct authorization checks in Snipe-IT. The primary /stored-eula-file/{filename} route correctly denies access to non-owners. However, the secondary /account/stored-eula-file/{filename} route inside ProfileController performed an insufficient check, allowing any authenticated user to fetch a signed EULA file if they possessed its filename. In parallel, the API endpoint /api/v1/users/{target_id}/eulas authorized against the generic User class rather than the specific target user object. As a result, a restricted user could list another user's EULAs and obtain the randomized filenames required for the download route.
Root Cause
The root cause is inconsistent enforcement of object-level authorization. In UsersController::eulas, the call $this->authorize('view', User::class) only checks whether the caller can view users in general, not whether they can view the specific $user targeted by the request. In ProfileController, the file-serving action resolved the Actionlog record by filename but only compared auth()->id() against target_id with a manager-style fallback, without invoking the policy against both the target and the owning user of the log entry.
Attack Vector
An authenticated attacker with any low-privileged Snipe-IT account issues a request to /api/v1/users/{target_id}/eulas, iterating target_id values to enumerate other accounts. The response contains the randomized filenames of signed EULA PDFs. The attacker then requests /account/stored-eula-file/{filename} to download each file directly from the configured filesystem or a signed S3 URL.
// Patch: app/Http/Controllers/Api/UsersController.php
public function eulas(User $user, ActionlogsTransformer $transformer)
{
- $this->authorize('view', User::class);
+ $this->authorize('view', $user);
$eulas = $user->eulas;
// Patch: app/Http/Controllers/ProfileController.php
$filename = basename((string) $filename);
-$logentry = Actionlog::where('filename', $filename)->first();
+$logentry = Actionlog::where('filename', $filename)->with('user', 'target')->first();
-// Make sure the user has permission to view this file
-$allowed_to_view_users_assets = Gate::allows('view', User::class) && Gate::allows('view', Asset::class);
-
-if (auth()->id() != $logentry->target_id && ! $allowed_to_view_users_assets) {
- return redirect()->route('account')->with('error', trans('general.generic_model_not_found', ['model' => 'file']));
+if (! $logentry) {
+ return redirect()->back()->with('error', trans('general.record_not_found'));
}
+$this->authorize('view', $logentry->target);
+$this->authorize('view', $logentry->user);
Source: GitHub Commit f15d786
Detection Methods for CVE-2026-55694
Indicators of Compromise
- Repeated authenticated requests to /api/v1/users/{target_id}/eulas where the calling user's ID does not match target_id.
- HTTP 200 responses on /account/stored-eula-file/{filename} for filenames not associated with the requesting user's Actionlog records.
- Sequential enumeration patterns across target_id values from a single session or IP.
Detection Strategies
- Parse Snipe-IT web server access logs and correlate the target_id path parameter with the authenticated session identity.
- Alert when a non-admin account issues API calls to /users/{id}/eulas for IDs other than its own.
- Baseline normal EULA download volume per user and flag outliers.
Monitoring Recommendations
- Enable Laravel audit logging and forward web tier logs to a centralized SIEM for retention and correlation.
- Monitor S3 private bucket access logs for private_uploads/eula-pdfs/ object retrievals tied to short-lived signed URLs.
- Review Snipe-IT Actionlog entries for EULA acceptance and file-view actions that do not correspond to user activity.
How to Mitigate CVE-2026-55694
Immediate Actions Required
- Upgrade Snipe-IT to version 8.6.3 or later, which contains the authorization fix.
- Rotate any signed EULA files that may contain sensitive PII, and reissue if necessary.
- Audit application logs since deployment for unauthorized access to /api/v1/users/*/eulas and /account/stored-eula-file/*.
Patch Information
The fix is delivered in Snipe-IT v8.6.3. Commit f15d786 replaces the generic authorize('view', User::class) call with an object-scoped authorize('view', $user) check in UsersController, and enforces authorize('view', $logentry->target) and authorize('view', $logentry->user) in ProfileController before serving files. See the GitHub Security Advisory GHSA-3hgv-jr5j-cg9x for the full advisory.
Workarounds
- Restrict access to the Snipe-IT web interface to trusted networks or VPN until the upgrade is applied.
- Temporarily disable the EULA acknowledgement feature or remove routing to /account/stored-eula-file/{filename} at the reverse proxy layer.
- Reduce the number of accounts granted authenticated access to the application to limit exposure.
# Upgrade Snipe-IT to the patched release
git fetch --tags
git checkout v8.6.3
composer install --no-dev --prefer-source
php artisan migrate --force
php artisan config:clear && php artisan cache:clear
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

