CVE-2026-61456 Overview
CVE-2026-61456 is a stored Cross-Site Scripting (XSS) vulnerability in the Grav API plugin (getgrav/grav-plugin-api) before version 1.0.3. The flaw resides in the POST /api/v1/media endpoint, which accepts SVG uploads without sanitization. The HandlesMediaUploads::processUploadedFile() method validates only the file extension and never calls Security::sanitizeSVG(). An authenticated attacker holding the api.media.write permission can upload an SVG containing arbitrary JavaScript. The file is stored unmodified and served with Content-Type: image/svg+xml, causing embedded scripts to execute in an administrator's browser session when opened. This weakness is tracked as [CWE-79].
Critical Impact
Script execution in an administrator's authenticated session enables cookie theft, session hijacking, and account takeover of the Grav CMS.
Affected Products
- Grav API plugin (getgrav/grav-plugin-api) versions prior to 1.0.3
- Grav CMS deployments exposing the media upload API
- Any Grav instance granting the api.media.write permission to non-administrator users
Discovery Timeline
- 2026-07-10 - CVE-2026-61456 published to the National Vulnerability Database
- 2026-07-10 - Last updated in NVD database
Technical Details for CVE-2026-61456
Vulnerability Analysis
The Grav API plugin exposes POST /api/v1/media to allow authenticated clients to upload media assets. The upload handler, HandlesMediaUploads::processUploadedFile(), performs extension-based validation but omits content inspection for SVG files. Scalable Vector Graphics (SVG) is an XML-based format that legitimately supports <script> elements, event handlers such as onload, and embedded JavaScript URIs.
Because the file bytes reach disk unaltered and are later served with Content-Type: image/svg+xml, any browser rendering the resource executes its scripts under the origin of the Grav site. When an administrator navigates to the uploaded asset directly, or when it is embedded via <object> or <iframe> on another page, the payload runs inside the administrative session.
Root Cause
The root cause is missing input sanitization. Grav ships a Security::sanitizeSVG() helper that strips scripts and dangerous attributes, but the API upload path never invokes it. The plugin trusts the .svg extension and MIME type without parsing the XML body, so malicious markup persists through the storage and retrieval pipeline.
Attack Vector
Exploitation requires an authenticated account with the api.media.write permission. The attacker crafts an SVG whose XML body contains a <script> block or an event handler that performs actions such as reading document.cookie or issuing authenticated requests to /api/v1/. The file is uploaded through the media API, stored in Grav's user content directory, and later triggered when an administrator opens the media manager or a URL referencing the uploaded asset. The resulting script runs in the administrator's origin and can exfiltrate session identifiers or issue privileged API calls.
No verified exploit code is publicly available. Refer to the GitHub Security Advisory and the VulnCheck Advisory on Grav XSS for technical details.
Detection Methods for CVE-2026-61456
Indicators of Compromise
- SVG files in Grav's user/pages/ or user/data/ directories containing <script>, javascript:, or on*= event handler attributes.
- POST /api/v1/media requests with Content-Type: image/svg+xml originating from non-administrative accounts.
- Outbound HTTP requests from administrator browsers to unfamiliar domains shortly after opening the Grav media manager.
- Unexpected session tokens or API keys appearing in web server access logs from external addresses.
Detection Strategies
- Scan the media store for SVG files whose XML contains <script>, <foreignObject>, or on[a-z]+= attributes using YARA or grep.
- Parse web server logs for POST /api/v1/media uploads correlated with subsequent GET requests to the same asset from administrator IP ranges.
- Deploy Content Security Policy (CSP) violation reporting to surface unauthorized script execution attempts on Grav pages.
Monitoring Recommendations
- Alert on any user other than trusted administrators uploading .svg files through the Grav API.
- Track file integrity in user/pages/ and compare hashes of served media against a known-good baseline.
- Monitor administrator sessions for anomalous API calls immediately after opening media assets.
How to Mitigate CVE-2026-61456
Immediate Actions Required
- Upgrade the Grav API plugin to version 1.0.3 or later, where Security::sanitizeSVG() is invoked during upload processing.
- Revoke the api.media.write permission from any account that does not require media uploads.
- Audit existing SVG files in the media library and remove or sanitize any containing scripts or event handlers.
Patch Information
The fix is delivered in getgrav/grav-plugin-api 1.0.3. The updated HandlesMediaUploads::processUploadedFile() method routes SVG uploads through Security::sanitizeSVG() before persistence. Details are available in the GitHub Security Advisory GHSA-7vhm-8x52-2r5p.
Workarounds
- Block SVG uploads at the web server or reverse proxy layer until the plugin is upgraded.
- Configure the server to serve stored SVG files with Content-Disposition: attachment so browsers download rather than render them.
- Apply a strict Content Security Policy that disallows inline scripts on Grav administrative pages.
- Restrict the /api/v1/media endpoint to authenticated administrator IP ranges via web application firewall rules.
# Nginx snippet: force SVGs to download instead of executing scripts
location ~* \.svg$ {
add_header Content-Disposition "attachment";
add_header Content-Security-Policy "default-src 'none'; script-src 'none'";
types { image/svg+xml svg; }
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

