CVE-2026-86749 Overview
CVE-2026-86749 is a data integrity vulnerability in Snipe-IT, an open source IT asset management application. Versions <= 8.6.3 fail to check the return value of storage write operations in ImageUploadRequest::handleImages(). When a transient storage backend failure occurs during an image upload, the application deletes the prior image and updates the database to reference a file that was never written. A parallel defect in deleteExistingImage() nulls the model's image field even when the underlying Storage::delete() call fails. The result is unrecoverable image loss and durable database-to-disk inconsistency across every model routed through the affected upload handler.
Critical Impact
Any authenticated user uploading an image during a storage backend failure can trigger permanent loss of the prior image and leave the Snipe-IT database referencing a nonexistent file, requiring manual reconciliation.
Affected Products
- Snipe-IT versions <= 8.6.3 (fixed in 8.7.0)
- All models routed through ImageUploadRequest::handleImages() (assets, asset models, users, companies, manufacturers, locations, categories, suppliers, departments)
- Deployments backed by transient-failure-prone storage such as Amazon S3, local filesystems with quota limits, or restricted permissions
Discovery Timeline
- 2026-09-09 - CVE-2026-86749 published to the National Vulnerability Database (NVD)
- 2026-09-09 - Last updated in NVD database
Technical Details for CVE-2026-86749
Vulnerability Analysis
The defect falls under [CWE-252]: Unchecked Return Value. Snipe-IT's ImageUploadRequest::handleImages() invokes Laravel's Storage::disk('public')->put(...) to persist uploaded images but never inspects the boolean return value. Laravel's default disk mode returns false on failure rather than throwing an exception, so the calling code proceeds as if the write succeeded.
After the silent failure, the handler calls deleteExistingImage() to remove the previous file and then reassigns the model's image attribute to the new filename before persisting the Eloquent model. The database row now references a filename that does not exist on disk. The previously valid image is destroyed.
A mirror flaw exists inside deleteExistingImage(). A failed Storage::delete() call still results in the model's image field being nulled, orphaning the file on disk when deletion did not actually succeed.
Root Cause
The root cause is missing error handling around Laravel filesystem operations. Neither the write path nor the delete path validates the return status before mutating persistent model state. Any transient storage condition, such as an S3 network error, local filesystem permission issue, or disk quota exhaustion, produces the inconsistency.
Attack Vector
The condition is not directly attacker-controlled. It is triggered when any legitimate authenticated user submits an image upload while the storage backend transiently fails. Exploitation requires low privileges and user interaction, but the failure window is environmental rather than crafted. Environments with unstable object storage or constrained local disks are most exposed.
No verified proof-of-concept code is published. Refer to the GitHub Security Advisory GHSA-v37p-hr9x-5w85 and the VulnCheck Advisory: Snipe-IT Data Loss for the maintainer's technical write-up.
Detection Methods for CVE-2026-86749
Indicators of Compromise
- Database rows in Snipe-IT tables referencing image filenames under public/uploads/ that do not exist on the storage backend.
- Orphaned image files present on disk or in the S3 bucket with no matching model row referencing them.
- Application or web server logs showing Storage::disk('public')->put operations coinciding with S3 5xx responses, EACCES, or ENOSPC errors.
Detection Strategies
- Run a reconciliation script that iterates every image-carrying model and verifies each image column value resolves to an existing file on the configured disk.
- Correlate PHP error logs and storage backend telemetry for write or delete failures that occur within the same request as a Snipe-IT model update.
- Audit S3 access logs or filesystem audit logs for PutObject failures during authenticated Snipe-IT upload sessions.
Monitoring Recommendations
- Alert on any non-2xx response from the storage backend for write operations originating from the Snipe-IT application service account.
- Track filesystem used capacity, inode consumption, and permission changes on directories backing the public disk.
- Monitor Snipe-IT audit trail entries for image field updates against models where the referenced file cannot be located.
How to Mitigate CVE-2026-86749
Immediate Actions Required
- Upgrade Snipe-IT to version 8.7.0 or later, which validates return values from Storage::disk('public')->put(...) and Storage::delete() before mutating model state.
- Take a backup of the database and the public/uploads/ directory before applying the upgrade to preserve any recoverable images.
- Execute a reconciliation pass after upgrading to identify and repair rows already left in an inconsistent state.
Patch Information
The maintainers fixed the issue in Snipe-IT 8.7.0. Details are documented in the GitHub Security Advisory GHSA-v37p-hr9x-5w85. Administrators should follow the standard Snipe-IT upgrade procedure and clear the application cache after deploying the patched release.
Workarounds
- Restrict image upload permissions to a minimal set of trusted operators until the patch is applied.
- Ensure the storage backend is provisioned with sufficient quota, correct permissions, and stable network connectivity to minimize transient failures.
- Schedule frequent backups of both the database and the image storage location so lost images can be restored from the most recent snapshot.
# Configuration example
# Upgrade Snipe-IT to the patched release
cd /var/www/snipe-it
git fetch --tags
git checkout v8.7.0
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.

