CVE-2025-64747 Overview
CVE-2025-64747 is a stored cross-site scripting (XSS) vulnerability in Directus, a real-time API and application dashboard for managing SQL database content. The flaw affects all versions prior to 11.13.0 and resides in the Block Editor interface. Authenticated users holding upload files and edit item permissions can inject malicious JavaScript that persists in stored content. Attackers bypass Content Security Policy (CSP) restrictions by combining file uploads with iframesrcdoc attributes, achieving persistent script execution in the context of other users viewing the affected records.
Critical Impact
Authenticated low-privileged users can inject persistent JavaScript that executes in the browsers of administrators and editors, enabling session theft, account takeover, and data exfiltration through CSP bypass.
Affected Products
- Monospace Directus versions prior to 11.13.0
- Directus Block Editor interface (input-block-editor)
- Node.js deployments of Directus using the affected component
Discovery Timeline
- 2025-11-13 - CVE-2025-64747 published to the National Vulnerability Database
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-64747
Vulnerability Analysis
The vulnerability is a stored XSS issue [CWE-20: Improper Input Validation] in the Directus Block Editor. The editor accepts structured block data and renders it back to users without sanitizing embedded HTML or attribute payloads. Because the injected content is persisted to the underlying database, every subsequent viewer of the affected record triggers execution of the attacker-controlled JavaScript.
Exploitation requires low-privilege authenticated access with upload files and edit item permissions and user interaction from a victim who opens the affected item. The impact affects confidentiality, integrity, and availability of the victim session, including token theft, unauthorized API calls under the victim's identity, and defacement of managed content.
Root Cause
The Block Editor persisted EditorJS output data without validating or sanitizing block-level fields. The fix in commit d23525317f0780f04aa1fe7a99171a358e43cb2e introduces a dedicated sanitize.ts module that walks each block and cleans its data payload with dompurify before rendering, removing the ability to persist executable HTML.
Attack Vector
An authenticated attacker uploads a crafted file and edits an item that uses the Block Editor. They inject an iframe element whose srcdoc attribute contains attacker-controlled HTML and JavaScript. Because srcdoc renders inline HTML inside the frame under the parent origin's document context in a way that sidesteps the CSP applied to remote script sources, the payload executes when any user later opens the item.
// Patch: app/src/interfaces/input-block-editor/sanitize.ts
import { isObject } from '@directus/utils';
import { OutputBlockData } from '@editorjs/editorjs';
import dompurify from 'dompurify';
import { cloneDeep, isString } from 'lodash';
export function sanitizeValue(value: any): EditorJS.OutputData | null {
if (!value || typeof value !== 'object' || !value.blocks || value.blocks.length === 0) return null;
const sanitizedBlocks = value.blocks.map((block: OutputBlockData) => ({
...block,
data: sanitizeBlockData(block.data),
}));
if (sanitizedBlocks.length === 0) return null;
return cloneDeep({
time: value?.time || Date.now(),
version: value?.version || '0.0.0',
blocks: sanitizedBlocks,
});
}
export function sanitizeBlockData(data: unknown): unknown {
if (Array.isArray(data)) {
return data.map((item: unknown) => sanitizeBlockData(item));
}
if (isObject(data)) {
const cleaned: Record<string, unknown> = {};
// dompurify applied to string fields before persistence
}
}
Source: Directus commit d2352531
Detection Methods for CVE-2025-64747
Indicators of Compromise
- Block Editor field values containing <iframe tags or srcdoc attributes in stored records
- Uploaded files with HTML or JavaScript MIME types referenced by Block Editor content
- Unexpected outbound requests from administrator browser sessions viewing Directus items
- Directus audit log entries showing items.update from low-privileged accounts on high-value collections
Detection Strategies
- Query the Directus database for Block Editor JSON payloads containing <script, srcdoc=, javascript:, or on[a-z]+= handler patterns
- Review the directus_activity and directus_revisions tables for edits made by accounts holding only upload files and edit item permissions
- Correlate file uploads with subsequent item edits by the same actor within short time windows
Monitoring Recommendations
- Alert on browser telemetry showing script execution originating from Directus admin app routes
- Monitor CSP violation reports for frame-src and child-src directives generated by the Directus admin interface
- Track privilege escalation attempts and API token creation events immediately following Block Editor item views
How to Mitigate CVE-2025-64747
Immediate Actions Required
- Upgrade Directus to version 11.13.0 or later, which introduces the sanitizeValue routine backed by dompurify
- Audit user roles and revoke upload files and edit item permissions from accounts that do not require them
- Review recent Block Editor content for injected iframe or srcdoc payloads and purge malicious entries
- Rotate administrator session tokens and API keys that may have been exposed to a viewing victim
Patch Information
The fix is delivered in Directus 11.13.0 via commit d23525317f0780f04aa1fe7a99171a358e43cb2e. It adds app/src/interfaces/input-block-editor/sanitize.ts, which sanitizes each OutputBlockData entry before rendering or persisting. See the GitHub Security Advisory GHSA-vv2v-pw69-8crf for the official vendor notice.
Workarounds
- Disable the Block Editor interface for collections where it is not strictly required until the upgrade is applied
- Restrict upload files permissions to trusted roles and enforce strict file MIME type allow-lists
- Deploy a stricter CSP that forbids frame-src 'self' where feasible to limit iframe-based execution paths
# Upgrade Directus to the patched release
npm install directus@11.13.0
# Verify installed version
npx directus --version
# Restart the Directus service after upgrade
systemctl restart directus
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.
