GHSA-P68W-RGMG-3C2V

Vulnerability from github – Published: 2026-06-23 23:02 – Updated: 2026-06-23 23:02
VLAI
Summary
Snipe-IT Vulnerable to User Account Escalation via CSV Import
Details

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

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "snipe/snipe-it"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "8.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-49976"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-23T23:02:03Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Impact\nThe CSV user import in update mode bypasses user-edit authorization. A user with only the `import` permission can overwrite any non-admin user\u0027s email by uploading a CSV, then trigger a password reset to take over the account.\n\n`UserImporter.php` checks the `canEditAuthFields` gate and tries to strip auth fields from the model:\n\n```php\n// app/Importer/UserImporter.php:107-114\nif (Auth::check() \u0026\u0026 (! Gate::allows(\u0027canEditAuthFields\u0027, $user))) {\n    unset($user-\u003eusername);\n    unset($user-\u003eemail);\n    unset($user-\u003epassword);\n    unset($user-\u003eactivated);\n}\n$user-\u003eupdate($this-\u003esanitizeItemForUpdating($user));\n```\n\nThe `unset()`s operate on the model, but `sanitizeItemForUpdating()` rebuilds its array from `$this-\u003eitem` (the raw CSV row), not from the model:\n\n```php\n// app/Importer/ItemImporter.php:135-149\nprotected function sanitizeItemForStoring($model, $updating = false)\n{\n    $item = collect($this-\u003eitem);                  // CSV data, not model attributes\n    $item = $item-\u003eonly($model-\u003egetFillable());\n    if ($updating) {\n        $item = $item-\u003ereject(fn($v) =\u003e empty($v));\n    }\n    return $item-\u003etoArray();\n}\n```\n\nThe attacker\u0027s CSV values pass through untouched.\n\nFor 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-\u003eauthorize(\u0027import\u0027)` (`ImportController.php:196`); no `users.edit` check anywhere. The normal API route `PATCH /api/v1/users/{id}` correctly returns 403 for the same user. \n\nAttacker must have import privileges to exploit this, and that permission must be granted specifically and intentionally by a superadmin.\n\n\n### Patches\nPatched in v8.6.0",
  "id": "GHSA-p68w-rgmg-3c2v",
  "modified": "2026-06-23T23:02:03Z",
  "published": "2026-06-23T23:02:03Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/grokability/snipe-it/security/advisories/GHSA-p68w-rgmg-3c2v"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/grokability/snipe-it"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Snipe-IT Vulnerable to User Account Escalation via CSV Import"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…