Human
Machine
REPRO-2026-00112 HIGH XSS
Verified
Statamic CMS Stored XSS via Markdown Fieldtype
statamic/cms (composer) Feb 20, 2026
What's the vulnerability?
No summary available
Root Cause Analysis
# Root Cause Analysis Report
## Summary
This report documents a stored Cross-Site Scripting (XSS) vulnerability in Statamic CMS identified as GHSA-8r7r-f4gm-wcpq (CVE-2026-27196). The vulnerability exists in the `HtmlFieldtype.vue` component, which renders raw HTML content without sanitization. Authenticated users with field management permissions can inject malicious JavaScript code into HTML field configurations, which executes when viewed by higher-privileged users (such as administrators) in the Control Panel. This enables privilege escalation attacks where a lower-privileged user can potentially compromise admin accounts.
## Impact
**Package:** statamic/cms (Composer)
**Affected Versions:**
- `>= 6.0.0-alpha.1, < 6.3.2`
- `< 5.73.9`
**Patched Versions:** 6.3.2, 5.73.9
**Risk Level:** HIGH (CVSS 8.1)
**CVSS Vector:** `CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:N`
**Consequences:**
- Privilege escalation via stored XSS
- Malicious JavaScript execution in admin context
- Potential account takeover of higher-privileged users
- Data theft and unauthorized administrative actions
## Root Cause
The vulnerability stems from improper output encoding in the `HtmlFieldtype.vue` component. The original code directly renders user-controlled HTML content using Vue's `v-html` directive without any sanitization:
```vue
<template>
<div v-html="config.html" />
</template>
<script>
import Fieldtype from './Fieldtype.vue';
export default {
mixins: [Fieldtype],
};
</script>
```
The `config.html` property is set by users with field management permissions when configuring HTML fieldtypes. Since the content is rendered directly without sanitization, an attacker can inject malicious JavaScript such as:
```html
<script>fetch('/admin/users/create?email=attacker@evil.com&password=backdoor123')</script>
```
When an administrator views a form containing this malicious HTML field, the JavaScript executes in their browser with their authenticated session.
**Fix Commit:** https://github.com/statamic/cms/commit/11ae40e62edd3da044d37ebf264757a09cc2347b
The fix adds DOMPurify library to sanitize HTML content before rendering:
```vue
<script setup>
import Fieldtype from '@/components/fieldtypes/fieldtype';
import { computed } from 'vue';
import DOMPurify from 'dompurify';
const props = defineProps(Fieldtype.props);
const html = computed(() => props.config.sanitize ? DOMPurify.sanitize(props.config.html) : props.config.html);
</script>
<template>
<div v-html="html" />
</template>
```
## Reproduction Steps
The reproduction script `repro/reproduction_steps.sh` performs the following:
1. Clones Statamic CMS repository at the vulnerable version (v6.3.1)
2. Examines the `resources/js/components/fieldtypes/HtmlFieldtype.vue` file
3. Detects the presence of the vulnerable pattern: `v-html="config.html"` without sanitization
4. Confirms DOMPurify is NOT present in the file
5. Generates evidence logs showing the vulnerable code
**To run:**
```bash
./repro/reproduction_steps.sh
```
**Expected Output:**
- Confirmation that `v-html="config.html"` is present in the file
- Confirmation that DOMPurify sanitization is NOT present
- Exit code 0 indicating vulnerability confirmed
## Evidence
**Log Files:**
- `logs/clone.log` - Git clone output
- `logs/html_fieldtype_original.vue` - Full content of vulnerable component
- `logs/vulnerability.confirmed` - Confirmation of vulnerable pattern
- `logs/vulnerable_code.vue` - Copy of vulnerable source code
- `logs/patch.diff` - Diff of the security fix (if fetched)
**Key Evidence Excerpts:**
From `logs/vulnerable_code.vue`:
```vue
<template>
<div v-html="config.html" />
</template>
<script>
import Fieldtype from './Fieldtype.vue';
export default {
mixins: [Fieldtype],
};
</script>
```
The presence of `v-html="config.html"` without any sanitization library (DOMPurify) confirms the vulnerability exists in this version.
## Recommendations / Next Steps
**Immediate Actions:**
1. Upgrade to Statamic CMS 6.3.2 or 5.73.9 (or later)
2. Audit existing HTML fieldtype configurations for malicious content
3. Review access logs for suspicious admin activity
**Fix Approach:**
The vendor has correctly addressed this issue by:
1. Adding DOMPurify library for HTML sanitization
2. Adding a configurable `sanitize` toggle (default: true)
3. Wrapping the HTML content in a computed property that applies sanitization
**Testing Recommendations:**
1. Add automated tests that verify XSS payloads are sanitized
2. Implement Content Security Policy (CSP) headers as defense in depth
3. Regular security audits of fieldtype components
4. Consider using Vue's text interpolation (`{{ }}`) instead of `v-html` where possible
**Defense in Depth:**
- Implement strict CSP headers to prevent inline script execution
- Enable the `sanitize` option in HTML fieldtype configurations
- Regularly audit user permissions for field management capabilities
## Additional Notes
**Idempotency Confirmation:**
The reproduction script has been tested and passes consistently on consecutive runs. It:
- Cleans up previous runs (`rm -rf` on statamic directory)
- Performs fresh git clone each time
- Produces identical results confirming the vulnerability exists in v6.3.1
**Edge Cases / Limitations:**
- This reproduction demonstrates the code-level vulnerability but does not set up a full Statamic instance with database
- Full exploitation would require an actual Statamic installation with:
- A user account with field management permissions
- An admin user to view the malicious form
- The JavaScript payload would execute in the admin's browser session
- The vulnerability requires authenticated access with specific permissions (field management)
- The CVSS score reflects required user interaction (UI:R) and high privileges (PR:H)
**Related CVEs:**
- CVE-2026-27196: The primary identifier for this vulnerability
- GHSA-8r7r-f4gm-wcpq: GitHub Security Advisory identifier
**Additional References:**
- https://github.com/statamic/cms/security/advisories/GHSA-8r7r-f4gm-wcpq
- https://github.com/statamic/cms/commit/6c270dacc2be02bfc2eee500766f3309f59d47b3 (5.x fix)
- https://dbugs.ptsecurity.com/vulnerability/PT-2026-20984
One Command
Verify with pruva-verify
Run the Pruva CLI to automatically fetch and execute the reproduction script.
pruva-verify REPRO-2026-00112 or
pruva-verify GHSA-8r7r-f4gm-wcpq or
pruva-verify CVE-2026-27197 Install:
curl -fsSL https://pruva.dev/install.sh | sh Or Run Manually
1
Download the script
curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00112/artifacts/reproduction_steps.sh 2
Make executable
chmod +x reproduction_steps.sh 3
Run the script
./reproduction_steps.sh Run in a VM, container, or disposable environment. This exploits a real vulnerability.
How Pruva Reproduced This
Watch the AI agent's step-by-step process.
Loading session...
Artifacts
No artifacts available