MEDIUM 4.6

CVE-2026-61456: Grav API Plugin SVG Upload XSS Allows Admin Session Hijacking

The Grav API plugin before version 1.0.3 contains a stored cross-site scripting (XSS) vulnerability in its media upload handler. An authenticated user with API media write permissions can upload an SVG file containing malicious JavaScript. Because the plugin fails to sanitize SVG content and serves the file with an image MIME type, opening the file in a browser causes the embedded script to execute in the administrator's session context. This allows attackers to steal session cookies or hijack admin sessions without requiring any additional user interaction beyond the attacker uploading the payload.

Source data · NVD / CISA · public domain

CVSS
3.1 · 4.6 MEDIUM · CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:N
Weaknesses (CWE)
CWE-79
Affected products
0 configuration(s)
Published / Modified
2026-07-10 / 2026-07-10

NVD description (verbatim)

The Grav API plugin (getgrav/grav-plugin-api) before 1.0.3 fails to sanitize SVG files uploaded through the POST /api/v1/media endpoint. The HandlesMediaUploads::processUploadedFile() method validates only the file extension and never invokes Security::sanitizeSVG(), so an authenticated attacker with 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; when an administrator opens it in a browser (directly or via <object>/<iframe>), the embedded script executes in their session context, enabling cookie theft and session hijacking.

3 reference(s) · View on NVD →

SEC.co analysis · AI-assisted, reviewed against source

Technical summary

CVE-2026-61456 stems from insufficient input validation in the Grav API plugin's HandlesMediaUploads::processUploadedFile() method. The method performs file extension checking but does not invoke the Security::sanitizeSVG() function, which exists elsewhere in the codebase and is designed to strip dangerous content from SVG uploads. An attacker with the api.media.write permission sends a POST request to /api/v1/media containing an SVG file with embedded JavaScript (e.g., using <script> tags or event handlers). The file is stored unmodified on disk. When an administrator accesses the file—either via direct browser navigation or through an HTML <object> or <iframe> element—the browser parses the SVG and executes the embedded script in the context of the admin's authenticated session. This is a stored XSS variant because the malicious payload persists in the file system and triggers on every access.

Business impact

Compromise of administrator accounts is the primary risk. An attacker can steal session tokens or cookies, enabling complete takeover of the Grav installation without requiring the admin's password. Once hijacked, an admin session grants access to site content management, plugin configuration, and potentially underlying system access depending on Grav's deployment and permissions model. For organizations using Grav for content publishing or site management, this translates to potential data exfiltration, defacement, malware injection, or disruption of service. The attack requires prior authentication with limited permissions, so the attacker must already have valid API credentials—reducing but not eliminating the threat, as API access is often provisioned to external systems or contractors.

Affected systems

Grav installations with the API plugin installed and enabled are affected. Specifically, versions before 1.0.3 of the getgrav/grav-plugin-api package are vulnerable. The vulnerability is triggered only when an administrator or privileged user visits an uploaded SVG file in a browser context where scripts can execute. Organizations running Grav as a headless CMS or without browser-based access to media files may face reduced practical risk, though the vulnerability still exists.

Exploitability

Exploitation requires valid authentication with the api.media.write permission, making this a low-barrier attack for anyone with legitimate but limited API access. No special tools are needed—a simple POST request with an SVG payload suffices. The attack succeeds on all modern browsers without requiring admin interaction to 'click' anything; opening the file is sufficient. However, the attacker cannot force an administrator to view the file; they must wait for or socially engineer access. The CVSS score of 4.6 (Medium) reflects the authentication requirement and user interaction dependency, balanced against the high impact of successful session hijacking.

Remediation

Upgrade the Grav API plugin to version 1.0.3 or later. This patch adds sanitization of SVG uploads by calling Security::sanitizeSVG(), which strips or neutralizes dangerous JavaScript before storage. Organizations should verify the plugin version and apply the update as soon as testing permits. For defense-in-depth, restrict api.media.write permissions to trusted accounts only, consider storing uploaded media outside the web root, and serve media files with Content-Type: application/octet-stream or a restrictive content-security-policy header to prevent script execution.

Patch guidance

Install Grav API plugin version 1.0.3 or later. Verify the installed version via the Grav plugin manager or by checking the plugin's composer.json or version constant. Test the patch in a non-production environment to ensure compatibility with any custom API integrations before deploying to production. No configuration changes are required post-patch; the sanitization is automatic on upload.

Detection guidance

Audit existing SVG files in your Grav media directory for embedded JavaScript or event handlers. Search for patterns such as <script>, onerror=, onload=, or onclick= within .svg files. Review API access logs (if available) for uploads of SVG files by accounts with api.media.write permission, especially unexpected uploads. Monitor admin browser sessions for unauthorized access or session hijacking indicators. Implement file integrity monitoring on the media directory to detect unauthorized modifications.

Why prioritize this

While the CVSS score is Medium (4.6), the vulnerability enables direct session hijacking of administrators, the highest-trust accounts in a content management system. The fix is straightforward and low-risk, and the exploitation barrier is low for any insider or compromised account with limited API permissions. Prioritize patching as part of your regular vulnerability remediation cycle, especially if your organization uses the API plugin for content ingestion or integrations.

Risk score, explained

The CVSS v3.1 score of 4.6 reflects: (1) Network accessibility (AV:N) with low complexity (AC:L), increasing reachability; (2) requirement for Low privilege (PR:L), limiting the attacker pool to authenticated users; (3) user interaction (UI:R) requirement—an admin must open the file—which partially mitigates risk but is realistic in content management workflows; (4) scope unchanged (S:U) and no availability impact (A:N), but confidentiality and integrity impacts (C:L/I:L) from cookie theft and session hijacking. The score does not fully capture the criticality of admin compromise and should inform your risk tolerance; many organizations would treat this as High priority despite the numerical score.

Frequently asked questions

Can this vulnerability be exploited by unauthenticated users?

No. The attacker must have valid API credentials with the api.media.write permission. This significantly narrows the threat actor pool to insiders, contractors, or external systems with delegated access. However, if API keys are leaked or shared, this constraint is bypassed.

What happens if I serve media files from a CDN or separate domain?

Serving SVG files from a separate domain with restrictive headers (e.g., X-Content-Type-Options: nosniff, Content-Security-Policy: default-src 'none') can limit script execution. However, the root cause—unvalidated SVG uploads—remains. The patch is still necessary to prevent malicious files from being stored in the first place.

Does this vulnerability affect older versions of Grav without the API plugin?

No. The vulnerability is specific to the API plugin's media upload endpoint (/api/v1/media). Standard Grav installations without the API plugin are not affected.

Can I mitigate this without upgrading immediately?

Partial mitigation is possible: disable the API plugin if not in use, restrict api.media.write permissions to a minimal set of trusted accounts, and monitor SVG uploads closely. However, these are temporary measures; upgrading to 1.0.3 is the proper fix.

This analysis is based on the published CVE description and CVSS v3.1 scoring. No exploit code or weaponized proof-of-concept is provided. Organizations should verify patch availability and compatibility with their specific Grav version before deployment. Real-world impact may vary based on deployment architecture, network segmentation, and access control policies. This explainer is for informational purposes and does not constitute professional security advice; consult your security team or a qualified consultant for guidance specific to your environment. Source: NVD (public-domain), retrieved 2026-08-17. Analysis generated by SEC.co (claude-haiku-4-5).