GHSA-JHPH-5Q74-PMFX

Vulnerability from github – Published: 2026-08-28 17:59 – Updated: 2026-08-28 17:59
VLAI
Summary
Snipe-IT vulnerable to stored XSS via inline-served attachment
Details

Impact

A low-privilege user can store an active-content payload as an asset attachment and have it served inline, same-origin, with an active Content-Type, achieving stored XSS. The application sanitizes uploads only when PHP finfo detects image/svg+xml. By submitting an XHTML document whose finfo MIME is text/xml (an allowed extension), the svg-sanitize branch is skipped, the is stored raw, and the inline-serve path returns it as text/xml; charset=utf-8 with Content-Disposition: inline — which the browser renders as a live XHTML document and executes. The dedicated StorageHelper::allowSafeInline() whitelist that should have constrained inline-renderable types is never wired into the serve path.

Details

Vulnerable code — sanitizer keyed on finfo MIME app/Http/Requests/UploadFileRequest.php:46-53

$extension = $file->getClientOriginalExtension();
$file_name = $name_prefix.'-'.str_random(8).'-'.str_slug(...).'.'.$file->guessExtension();
...
if ($file->getMimeType() === 'image/svg+xml') {
    $uploaded_file = $this->handleSVG($file);   // svg-sanitize fires
} else {
    $uploaded_file = file_get_contents($file);   // stored RAW — no sanitization
}

Vulnerable code — inline serve, no allowSafeInline() app/Http/Controllers/UploadedFilesController.php:103

if (request('inline') == 'true') {
    $headers = ['Content-Disposition' => 'inline'];
    return Storage::download($path.$log->filename, $log->filename, $headers);
}

StorageHelper::allowSafeInline() (app/Helpers/StorageHelper.php:88) exists to whitelist inline-renderable types but is not called here. The validation rule (UploadFileRequest::rules()) is mimes: over config('filesystems.allowed_upload_extensions_for_validator'), which includes svg, xml, and txt — so a text/xml file passes validation and bypasses the SVG sanitizer simultaneously.

POC 1. From a fresh install, as a user with only assets.view + assets.files targeting any existing asset created by admin 2. click on the asset created by admin and upload files. 3. create a XML file with the following payload and upload it.

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><script>alert(document.cookie)</script></head>
<body>hi</body>
</html>
  1. Noticed that it did not receive any error and the file was uploaded.
  2. Now, can just get the URL and view it. (need to add the inline=true). image.png

Notice that the XSS was able to request document.cookie. This means that it is possible for low privilege user to perform XSS and perform privilege escalation to admin.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 8.6.1"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "snipe/snipe-it"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "8.6.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-55466"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-79"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-28T17:59:54Z",
    "nvd_published_at": "2026-07-10T20:16:46Z",
    "severity": "MODERATE"
  },
  "details": "### Impact\nA low-privilege user can store an active-content payload as an asset attachment and have it served inline, same-origin, with an active Content-Type, achieving stored XSS. The application sanitizes uploads only when PHP finfo detects image/svg+xml. By submitting an XHTML document whose finfo MIME is text/xml (an allowed extension), the svg-sanitize branch is skipped, the \u003cscript\u003e is stored raw, and the inline-serve path returns it as text/xml; charset=utf-8 with Content-Disposition: inline \u2014 which the browser renders as a live XHTML document and executes. The dedicated StorageHelper::allowSafeInline() whitelist that should have constrained inline-renderable types is never wired into the serve path.\n\n### Details\nVulnerable code \u2014 sanitizer keyed on finfo MIME `app/Http/Requests/UploadFileRequest.php:46-53`\n\n```php\n$extension = $file-\u003egetClientOriginalExtension();\n$file_name = $name_prefix.\u0027-\u0027.str_random(8).\u0027-\u0027.str_slug(...).\u0027.\u0027.$file-\u003eguessExtension();\n...\nif ($file-\u003egetMimeType() === \u0027image/svg+xml\u0027) {\n    $uploaded_file = $this-\u003ehandleSVG($file);   // svg-sanitize fires\n} else {\n    $uploaded_file = file_get_contents($file);   // stored RAW \u2014 no sanitization\n}\n```\n\nVulnerable code \u2014 inline serve, no `allowSafeInline()` `app/Http/Controllers/UploadedFilesController.php:103`\n\n```php\nif (request(\u0027inline\u0027) == \u0027true\u0027) {\n    $headers = [\u0027Content-Disposition\u0027 =\u003e \u0027inline\u0027];\n    return Storage::download($path.$log-\u003efilename, $log-\u003efilename, $headers);\n}\n```\n\n`StorageHelper::allowSafeInline()` (`app/Helpers/StorageHelper.php:88`) exists to whitelist inline-renderable types but is not called here. The validation rule (`UploadFileRequest::rules()`) is `mimes`: over `config(\u0027filesystems.allowed_upload_extensions_for_validator\u0027)`, which includes svg, xml, and txt \u2014 so a text/xml file passes validation and bypasses the SVG sanitizer simultaneously.\n\nPOC\n1. From a fresh install, as a user with only `assets.view` + `assets.files` targeting any existing asset created by admin\n2. click on the asset created by admin and upload files.\n3. create a XML file with the following payload and upload it.\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\"\u003e\n\u003chead\u003e\u003cscript\u003ealert(document.cookie)\u003c/script\u003e\u003c/head\u003e\n\u003cbody\u003ehi\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\n4. Noticed that it did not receive any error and the file was uploaded.\n5. Now, can just get the URL and view it. (need to add the `inline=true`).\nimage.png\n\nNotice that the XSS was able to request `document.cookie`. This means that it is possible for low privilege user to perform XSS and perform privilege escalation to admin.",
  "id": "GHSA-jhph-5q74-pmfx",
  "modified": "2026-08-28T17:59:54Z",
  "published": "2026-08-28T17:59:54Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/grokability/snipe-it/security/advisories/GHSA-jhph-5q74-pmfx"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-55466"
    },
    {
      "type": "WEB",
      "url": "https://github.com/grokability/snipe-it/commit/000cea0a622d586366cf60d2240c7c2a4b17c955"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/grokability/snipe-it"
    },
    {
      "type": "WEB",
      "url": "https://github.com/grokability/snipe-it/releases/tag/v8.6.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Snipe-IT vulnerable to stored XSS via inline-served attachment"
}



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…