GHSA-jhph-5q74-pmfx: XSS
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 <script> 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
php $extension = $file->getClientOriginalExtension(); $filename = $nameprefix.'-'.strrandom(8).'-'.strslug(...).'.'.$file->guessExtension(); ... if ($file->getMimeType() === 'image/svg+xml') { $uploadedfile = $this->handleSVG($file); // svg-sanitize fires } else { $uploadedfile = filegetcontents($file); // stored RAW — no sanitization }
Vulnerable code — inline serve, no allowSafeInline() app/Http/Controllers/UploadedFilesController.php:103
php 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.alloweduploadextensionsforvalidator'), 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 <?xml version="1.0"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head><script>alert(document.cookie)</script></head> <body>hi</body> </html>
4. Noticed that it did not receive any error and the file was uploaded. 5. 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.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
composer/snipe/snipe-itto a version that resolves this vulnerability.Fixed in 8.6.2 - Configuration
In app/Http/Controllers/UploadedFilesController.php (inline serve path), ensure StorageHelper::allowSafeInline() is enforced before returning inline-renderable content (the material states the whitelist exists in app/Helpers/StorageHelper.php:88 but is never wired into the serve path).
UploadedFilesController (inline serve) allowSafeInline() = called - Configuration
In app/Http/Requests/UploadFileRequest.php: rules(), adjust the `mimes` validation (based on config('filesystems.allowed_upload_extensions_for_validator'), which includes svg, xml, and txt) to exclude XML types such as text/xml so they do not bypass the SVG sanitizer branch.
UploadFileRequest (upload validation) rules() mimes over allowed extensions list = narrow to disallow text/xml and xml - Configuration
In app/Http/Requests/UploadFileRequest.php:46-53, do not key sanitization only on finfo detecting image/svg+xml. Ensure content that can be served inline (e.g., XML/XHTML with active content) is sanitized/blocked appropriately so an XHTML/XML payload cannot be stored raw and served inline as text/xml.
Upload handling/sanitization SVG sanitizer trigger condition = do not rely solely on finfo MIME image/svg+xml - Configuration
In the inline serve path (where request('inline') == 'true' enables inline Content-Disposition), restrict inline serving to the dedicated StorageHelper::allowSafeInline() whitelist so low-privilege users cannot make stored active-content payloads render as live documents.
Uploaded files inline behavior inline query/parameter = require inline=false by default or restrict inline to whitelisted types
Event History
Frequently Asked Questions
Which users can exploit this issue?
A low-privilege user who can upload an asset attachment can store the payload. Exploitation requires an XHTML document that is detected as text/xml and uses an allowed extension.
Who is at risk from a malicious attachment?
Users who open the uploaded attachment inline are exposed because it is served same-origin as text/xml with an inline Content-Disposition. A browser can render the document as active XHTML and execute its embedded script.
Does SVG upload sanitization prevent this attack?
No. Sanitization runs only when PHP finfo identifies the upload as image/svg+xml; an XHTML payload identified as text/xml bypasses that branch and is stored without sanitization.