Snipe-IT Vulnerable to User Account Escalation via CSV Import
Description
Impact
The CSV user import in update mode bypasses user-edit authorization. A user with only the import permission can overwrite any non-admin user's email by uploading a CSV, then trigger a password reset to take over the account.
UserImporter.php checks the canEditAuthFields gate and tries to strip auth fields from the model:
// app/Importer/UserImporter.php:107-114
if (Auth::check() && (! Gate::allows('canEditAuthFields', $user))) {
unset($user->username);
unset($user->email);
unset($user->password);
unset($user->activated);
}
$user->update($this->sanitizeItemForUpdating($user));
The unset()s operate on the model, but sanitizeItemForUpdating() rebuilds its array from $this->item (the raw CSV row), not from the model:
// app/Importer/ItemImporter.php:135-149
protected function sanitizeItemForStoring($model, $updating = false)
{
$item = collect($this->item); // CSV data, not model attributes
$item = $item->only($model->getFillable());
if ($updating) {
$item = $item->reject(fn($v) => empty($v));
}
return $item->toArray();
}
The attacker's CSV values pass through untouched.
For non-admin attacker vs. non-admin, non-superuser target, the gate returns true at AuthServiceProvider.php:137, so the unset() block never executes. The entire import path checks only $this->authorize('import') (ImportController.php:196); no users.edit check anywhere. The normal API route PATCH /api/v1/users/{id} correctly returns 403 for the same user.
Attacker must have import privileges to exploit this, and that permission must be granted specifically and intentionally by a superadmin.
Patches
Patched in v8.6.0
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
snipe/snipe-itPackagist | < 8.6.0 | 8.6.0 |
Patches
Vulnerability mechanics
Root cause
"The CSV import's authorization check only verifies the `import` permission and never checks `users.edit`, while the `sanitizeItemForUpdating()` method reads directly from the raw CSV row instead of the sanitized model object."
Attack vector
An attacker with only the `import` permission can upload a CSV file containing a target user's identifier and a new email address. Because `sanitizeItemForUpdating()` reads directly from the raw CSV row rather than the model, the email field is never stripped even when the `canEditAuthFields` gate would deny the edit. After the import overwrites the target's email, the attacker triggers a password reset to take over the account. The attacker must have been granted the `import` permission by a superadmin. [CWE-862]
Affected code
The vulnerability resides in `app/Importer/UserImporter.php` (lines 107–114) and `app/Importer/ItemImporter.php` (lines 135–149). The `unset()` calls on the model object are ineffective because `sanitizeItemForUpdating()` rebuilds the update array directly from the raw CSV row (`$this->item`), not from the modified model. Additionally, the import controller (`ImportController.php:196`) only checks the `import` permission and never verifies `users.edit` authorization.
What the fix does
The patch (v8.6.0) ensures that `sanitizeItemForUpdating()` operates on the sanitized model attributes rather than the raw CSV input, so the `unset()` calls that remove auth fields are effective. It also adds a proper `users.edit` authorization check to the import path, matching the protection already present on the direct API route `PATCH /api/v1/users/{id}`.
Preconditions
- authAttacker must have the `import` permission, which must be explicitly granted by a superadmin.
- authTarget user must be a non-admin, non-superuser account.
- inputAttacker must be able to upload a CSV file to the import endpoint.
Generated on Jun 24, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.