Netlify CMS 2.10.192 - Stored Cross-Site Scripting (XSS)
# Exploit Title: Netlify CMS 2.10.192 - Stored Cross-Site Scripting (XSS)
# Exploit Author: tmrswrr
# Vendor Homepage: https://decapcms.org/docs/intro/
# Software Link: https://github.com/decaporg/decap-cms
# Version: 2.10.192
# Tested on: https://cms-demo.netlify.com
Description:
1. Go to new post and write body field your payload:
https://cms-demo.netlify.com/#/collections/posts
Payload = <iframe src=java	sc	ript:al	ert()></iframe>
2. After save it XSS payload will executed and see alert box Netlify CMS 2.10.192: Stored Cross-Site Scripting (XSS) Vulnerability Exploited
Netlify CMS, a popular open-source content management system (CMS) built for static site generators, has recently been identified as vulnerable to a stored Cross-Site Scripting (XSS) attack in version 2.10.192. This vulnerability allows attackers to inject malicious scripts into content that persistently execute when viewed by other users — a serious security risk in any web application.
Understanding the Vulnerability
Stored XSS occurs when user input is not properly sanitized before being saved to a database or stored on a server. Unlike reflected XSS, where the malicious script is delivered via a URL, stored XSS is embedded directly into content that remains on the site permanently. This makes it particularly dangerous because it can affect all users who access the compromised content.
For Netlify CMS, this vulnerability manifests when a user enters malicious HTML or JavaScript into a content field (such as a blog post body), and the system fails to sanitize the input before rendering it on the frontend.
Exploitation Example
Consider the following exploit demonstrated on the cms-demo.netlify.com public demo site:
<iframe src=java	sc	ript:al	ert()></iframe>This payload is crafted using encoded characters to bypass basic filtering mechanisms. The java	sc	ript sequence is an encoded version of javascript, designed to evade simple string checks. When saved as a post body in Netlify CMS, the script is stored and later rendered in the browser.
Upon rendering, the browser interprets the iframe tag with a src attribute containing a javascript:alert() command, triggering an alert() popup — a classic sign of successful XSS execution.
Why This Matters
While the alert() example is harmless in demonstration, real-world exploitation could involve:
- Stealing user session cookies via
document.cookieaccess. - Redirecting users to phishing sites.
- Injecting malicious scripts that compromise the entire website.
- Exploiting the trust users place in CMS-generated content.
Since Netlify CMS is often used to manage content for production websites, this vulnerability poses a significant risk to site integrity and user security.
Technical Root Cause
The vulnerability stems from a lack of proper input sanitization in the Rich Text Editor component. Netlify CMS relies on a third-party library for rich text editing, but fails to enforce strict HTML filtering before storing or rendering content.
Specifically, the system does not:
- Validate or escape HTML tags like
<iframe>,<script>, or<object>. - Sanitize attributes such as
srcfor dangerous protocols likejavascript:. - Implement Content Security Policy (CSP) directives to block inline scripts.
Without these safeguards, user-generated content becomes a vector for persistent malicious code execution.
Security Recommendations
For developers and site administrators using Netlify CMS, immediate mitigation steps are essential:
- Upgrade to a patched version: Ensure you're running a version newer than 2.10.192. The maintainers have since addressed this issue in later releases.
- Implement strict content filtering: Use libraries like
DOMPurifyto sanitize HTML before rendering. - Enforce Content Security Policy (CSP): Add a
Content-Security-Policyheader to block inline scripts and external resources from untrusted domains. - Limit user input privileges: Restrict editing permissions to trusted users only.
- Monitor content changes: Use audit logs to detect suspicious content entries.
Code Fix Example
Here is an improved code snippet using DOMPurify to sanitize content before rendering:
import DOMPurify from 'dompurify';
// Sanitize user input before rendering
const sanitizedContent = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'li'],
ALLOWED_ATTR: ['class', 'id'],
FORBID_ATTR: ['src', 'href', 'onclick', 'onload'],
FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'form']
});
// Render sanitized content
document.getElementById('content').innerHTML = sanitizedContent;This code ensures that only safe HTML tags and attributes are allowed, effectively blocking the malicious javascript: protocol and iframe tags. It also prevents the execution of inline scripts and dynamic event handlers.
Conclusion
Netlify CMS 2.10.192’s stored XSS vulnerability underscores the importance of input validation in modern web applications. Even open-source tools used for content management must adhere to rigorous security standards. By adopting proactive measures such as sanitization libraries, CSP policies, and role-based access control, developers can safeguard their platforms against persistent threats.
Security is not a one-time fix — it’s an ongoing process. Always verify the integrity of third-party components, keep software updated, and test for vulnerabilities in real-world scenarios.