@tiptap/core, the rich-text editor engine embedded in countless AI writing assistants, chat composers, and document/agent-builder UIs, ships two regular expressions in its Markdown attribute parsers that exhibit quadratic backtracking on crafted input — a 20KB block-attribute string takes 1.4 seconds to parse versus 0.29ms for an equal-length benign string, and a 32KB inline-attribute string takes 2.2 seconds versus 0.19ms. With 15,633 downstream dependents this has a wide blast radius, though there is no EPSS score, no CISA KEV listing, and no public exploit or scanner template yet, and exploitation requires nothing more than pasting a short crafted string into any surface that renders attacker-controlled Markdown through this library — including AI copilots, chat threads, and collaborative document tools. A single request can freeze a browser tab or block a server event loop/worker, and because this runs during content parsing rather than execution, it silently degrades availability without generating obvious error signals. Patch to @tiptap/core 3.30.5 immediately on any product that parses user- or model-supplied Markdown through `createAtomBlockMarkdownSpec`, `createBlockMarkdownSpec`, or `createInlineMarkdownSpec`; if immediate patching isn't feasible, add input-length caps or timeouts around Markdown tokenization and monitor for anomalous CPU spikes or stalled event-loop metrics correlated with document save/render operations.
What is the risk?
Severity is rated high by the advisory (CWE-400/CWE-1333, algorithmic complexity DoS) but real-world urgency is moderated by the absence of CVSS scoring, EPSS data, CISA KEV inclusion, and any known public exploit or Nuclei template — this is a newly disclosed (2026-09-08), unweaponized vulnerability. Exploitability is nonetheless trivial: no authentication bypass, privilege escalation, or AI-specific knowledge is needed, only the ability to submit a short attacker-chosen string (as small as ~20-32KB) to any code path that tokenizes Markdown with the vulnerable helpers. The primary risk driver is exposure breadth — 15,633 packages depend on @tiptap/core, and any AI product embedding it as a chat, notes, or document-editing surface inherits the DoS risk wherever it renders untrusted Markdown (user input, RAG-retrieved content, or LLM-generated output fed back into the editor).
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Tokenizers | npm | >= 3.7.0, < 3.30.5 | 3.30.5 |
Do you use Tokenizers? You're affected.
How severe is it?
What should I do?
1 step-
Upgrade @tiptap/core to 3.30.5 or later, where the fix (commit d0d499b) adds boundary anchoring to the vulnerable regular expressions. If immediate upgrade isn't possible: enforce a hard length cap on Markdown input before tokenization (e.g., reject or truncate inputs with unusually long unbroken word-character or repeated-token runs), wrap Markdown parsing calls in a timeout/worker-thread sandbox so a hang doesn't take down the main process, and rate-limit document/message submission endpoints that trigger parsing. Detection: monitor for anomalous CPU/event-loop-lag spikes correlated with document save, chat-send, or preview-render operations, and audit logs for unusually long single-line tokens (repeated
__QUOTED_n__-style or long unbroken word-character sequences) in submitted content. Confirm exposure by checking whether your app actually invokescreateAtomBlockMarkdownSpec,createBlockMarkdownSpec, orcreateInlineMarkdownSpec— if you only load/save ProseMirror JSON, this CVE does not apply.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is GHSA-j95f-988m-3j2f?
@tiptap/core, the rich-text editor engine embedded in countless AI writing assistants, chat composers, and document/agent-builder UIs, ships two regular expressions in its Markdown attribute parsers that exhibit quadratic backtracking on crafted input — a 20KB block-attribute string takes 1.4 seconds to parse versus 0.29ms for an equal-length benign string, and a 32KB inline-attribute string takes 2.2 seconds versus 0.19ms. With 15,633 downstream dependents this has a wide blast radius, though there is no EPSS score, no CISA KEV listing, and no public exploit or scanner template yet, and exploitation requires nothing more than pasting a short crafted string into any surface that renders attacker-controlled Markdown through this library — including AI copilots, chat threads, and collaborative document tools. A single request can freeze a browser tab or block a server event loop/worker, and because this runs during content parsing rather than execution, it silently degrades availability without generating obvious error signals. Patch to @tiptap/core 3.30.5 immediately on any product that parses user- or model-supplied Markdown through `createAtomBlockMarkdownSpec`, `createBlockMarkdownSpec`, or `createInlineMarkdownSpec`; if immediate patching isn't feasible, add input-length caps or timeouts around Markdown tokenization and monitor for anomalous CPU spikes or stalled event-loop metrics correlated with document save/render operations.
Is GHSA-j95f-988m-3j2f actively exploited?
No confirmed active exploitation of GHSA-j95f-988m-3j2f has been reported, but organizations should still patch proactively.
How to fix GHSA-j95f-988m-3j2f?
Upgrade @tiptap/core to 3.30.5 or later, where the fix (commit d0d499b) adds boundary anchoring to the vulnerable regular expressions. If immediate upgrade isn't possible: enforce a hard length cap on Markdown input before tokenization (e.g., reject or truncate inputs with unusually long unbroken word-character or repeated-token runs), wrap Markdown parsing calls in a timeout/worker-thread sandbox so a hang doesn't take down the main process, and rate-limit document/message submission endpoints that trigger parsing. Detection: monitor for anomalous CPU/event-loop-lag spikes correlated with document save, chat-send, or preview-render operations, and audit logs for unusually long single-line tokens (repeated `__QUOTED_n__`-style or long unbroken word-character sequences) in submitted content. Confirm exposure by checking whether your app actually invokes `createAtomBlockMarkdownSpec`, `createBlockMarkdownSpec`, or `createInlineMarkdownSpec` — if you only load/save ProseMirror JSON, this CVE does not apply.
What systems are affected by GHSA-j95f-988m-3j2f?
This vulnerability affects the following AI/ML architecture patterns: agent frameworks, RAG pipelines, chat/collaboration UIs, content management pipelines.
What is the CVSS score for GHSA-j95f-988m-3j2f?
No CVSS score has been assigned yet.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0029 Denial of AI Service AML.T0034.001 Resource-Intensive Queries Compliance Controls Affected
What are the technical details?
Original Advisory
## Summary `@tiptap/core` contains two quadratic regular-expression denial-of-service paths in its default Markdown attribute parsers. Pandoc-style block attributes use two unanchored greedy expressions that rescan repeated `__QUOTED_0` prefixes. Inline shortcode attributes use another unanchored greedy key expression that rescans a long word-character run when no equals sign follows. The public `createAtomBlockMarkdownSpec` and `createBlockMarkdownSpec` helpers call the vulnerable Pandoc-style parser; `createInlineMarkdownSpec` calls the separately vulnerable shortcode parser. Using unmodified npm 3.29.2, a complete 20,508-byte atom-block token took approximately 1.40 seconds while an equal-length control took 0.29 ms. A complete 32,776-byte inline token took approximately 2.21 seconds while its equal-length control took 0.19 ms. Current repository `main` commit `5158212970344952dd9918b6a44bfb400d7fb6c1` retains both expressions. ## Block attribute root cause `packages/core/src/utilities/markdown/attributeUtils.ts` uses both `matchAll` and `replace` with `/([a-zA-Z][\w-]*)\s*=\s*(__QUOTED_\d+__)/g`. The candidate is `'__QUOTED_0'.repeat(n) + '__QUOTED_0__'`. There are no quotes, so the preceding replacement leaves it unchanged. At each `Q`, the greedy key-name expression consumes the remaining word-character run, the required equals sign fails, and the unanchored engine restarts at the next `Q`. This yields `O(n^2)` work, and the cleanup pass repeats it. A complete public-API proof is: ```js import { createAtomBlockMarkdownSpec } from '@tiptap/core' const tokenizer = createAtomBlockMarkdownSpec({ nodeName: 'probe' }).markdownTokenizer const attack = '__QUOTED_0'.repeat(2048) + '__QUOTED_0__' const source = `:::probe {${attack}} :::\n` const started = performance.now() tokenizer.tokenize(source, [], {}) console.log(performance.now() - started) ``` Measured complete-tokenizer timings were 6.23, 23.12, 88.93, 369.10, and 1,400.17 ms at 1,308, 2,588, 5,148, 10,268, and 20,508 bytes. Equal-length controls took 0.07 to 0.29 ms. The directly exported parser took 5,645.71 ms at 40,972 bytes while its control took 0.64 ms. ## Inline attribute root cause `packages/core/src/utilities/markdown/createInlineMarkdownSpec.ts` uses `/(\w+)=(?:"([^"]*)"|'([^']*)')/g`. For a long word-character run without an equals sign, `\w+` consumes the remaining suffix, `=` fails, and the unanchored engine restarts at the next character. The default inline tokenizer extracts this attacker string directly from a syntactically complete `[shortcode attributes]` token. ```js import { createInlineMarkdownSpec } from '@tiptap/core' const tokenizer = createInlineMarkdownSpec({ nodeName: 'probe', selfClosing: true }).markdownTokenizer const source = `[probe ${'0'.repeat(32768)}]` const started = performance.now() tokenizer.tokenize(source, [], {}) console.log(performance.now() - started) ``` At 1,032, 2,056, 4,104, 8,200, 16,392, and 32,776 bytes, candidates took 3.24, 12.88, 54.82, 136.91, 557.83, and 2,209.47 ms. Equal-length hyphen controls took 0.02 to 0.19 ms. ## Impact Applications parsing attacker-controlled Markdown with these helpers can have a browser main thread, server event loop, or worker blocked by a small input. Persisted documents can repeatedly freeze clients; repeated requests can exhaust server-side parsing capacity. Editors that only consume validated ProseMirror JSON and never invoke the Markdown parsing path are not directly affected through document content. ## History and remediation Commit `35645d94ae9cd73448a564104c2e08f64e9564bc` introduced both parsers on 14 October 2025, first released in 3.7.0. Versions 3.7.0 through current 3.29.2 and current `main` remain affected. Official issue, PR, and repository-advisory searches found no duplicate. Require a start-of-string or whitespace boundary before both key-value parsers, and preferably replace the multi-pass placeholder and shortcode regex designs with deterministic single-pass tokenizers. Keep quoted values out-of-band so attacker input cannot collide with predictable `__QUOTED_n__` placeholders. Add complete block and inline Markdown-tokenizer scaling regressions with equal-length controls. Please credit GitHub user `joostgrunwald` as finder/reporter.
Exploitation Scenario
An attacker interacts with an AI-powered writing tool, chat interface, or collaborative document app built on @tiptap/core's Markdown import feature — for example, pasting a message into a support chatbot, submitting a comment on a shared AI-generated document, or sending a crafted prompt that gets echoed back through the editor's Markdown renderer. The payload is a short, unremarkable-looking string (e.g., a long run of a repeated token with no whitespace, or a bracketed shortcode with a long unbroken suffix and no closing `=`) that triggers catastrophic backtracking the moment the tokenizer processes it. If parsed client-side, the victim's browser tab freezes; if parsed server-side (e.g., during document export, search indexing, or server-rendered previews), the Node.js event loop stalls, degrading or denying the editor service for every other user on that process — and because the payload is small (tens of kilobytes) and requires no authentication beyond whatever access the chat/editor already grants, an attacker can repeat it cheaply to sustain an outage.
Weaknesses (CWE)
CWE-1333 Inefficient Regular Expression Complexity
Primary
CWE-400 Uncontrolled Resource Consumption
Primary
CWE-1333 — Inefficient Regular Expression Complexity: The product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential.
- [Architecture and Design] Use regular expressions that do not support backtracking, e.g. by removing nested quantifiers.
- [System Configuration] Set backtracking limits in the configuration of the regular expression implementation, such as PHP's pcre.backtrack_limit. Also consider limits on execution time for the process.
Source: MITRE CWE corpus.
References
Timeline
Related Vulnerabilities
CVE-2026-41680 7.5 marked: infinite recursion DoS crashes Node.js via OOM
Same package: tokenizers CVE-2026-85670 6.5 tokenizers: malformed vocab crashes process (DoS)
Same package: tokenizers CVE-2026-12259 5.3 NLTK: unverified downloads allow malicious data swap
Same package: tokenizers CVE-2026-33660 10.0 TensorFlow: type confusion NPD in tensor conversion
Same attack type: DoS CVE-2023-25668 9.8 TensorFlow: unauthenticated RCE via heap buffer overflow
Same attack type: DoS