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-2025-11953

React Native's Open Door Policy: The Anatomy of CVE-2025-11953

Alon Barad
Alon Barad
Software Engineer

Feb 4, 2026·6 min read·78 visits

Executive Summary (TL;DR)

A critical RCE in @react-native-community/cli (Metro Server) allows attackers on the same network to execute arbitrary commands on a developer's machine via the `/open-url` endpoint. The server fails to sanitize input before passing it to the OS shell.

In the world of modern development, 'Developer Experience' (DX) is king. Tools are designed to be frictionless, magical, and zero-config. But sometimes, that magic involves binding a server to 0.0.0.0 and letting unauthenticated network traffic execute shell commands on your workstation. CVE-2025-11953 is a critical Remote Code Execution (RCE) vulnerability in the React Native CLI's Metro server that turns a developer's convenience into a hacker's playground.

The Hook: Convenience at a Cost

Let's set the scene. You're a React Native developer. You're sitting in a coffee shop, sipping an overpriced oat latte, iterating on your new app. Your phone is connected to your laptop, and the Metro Bundler is running, serving JavaScript bundles to your device. To make this seamless, the Metro server (part of @react-native-community/cli) typically binds to 0.0.0.0 (all interfaces) so your phone can reach it over the local network. It listens on port 8081.

Here's the problem: Metro isn't just serving static files. It includes 'middleware'—helper endpoints designed to improve your workflow. Specifically, it has endpoints like /open-url and /open-stack-frame. The idea is brilliant: if your app crashes on your phone, you tap a button, the phone sends a request to your laptop, and your laptop opens the offending file in VS Code or opens a documentation URL in Chrome. It's magical.

But for a security researcher, 'magic' usually translates to 'unvalidated input'. That helper endpoint is effectively a remote control for your operating system. And because the server binds to 0.0.0.0, that remote control isn't just in your hand—it's available to anyone on the same Wi-Fi network. That guy in the corner with the hoodie? He's not debugging his startup; he's scanning for port 8081.

The Flaw: Trusting User Input

The vulnerability (CWE-78) lies in how the Metro server handles requests to these helper endpoints. The logic was deceptively simple: receive a JSON payload containing a URL, and tell the operating system to 'open' that URL. On the surface, this looks like open('http://google.com').

However, under the hood, the library used to perform this action interacts with the underlying OS shell. On Windows specifically, this often translates to spawning a process via cmd.exe. The developers made a classic blunder: they took the input directly from the HTTP request body—data completely controlled by the user—and passed it into a command execution sink without strict sanitization.

It's the digital equivalent of a bank teller blindly accepting a note that says 'Give me all the money' because it was written on official-looking stationary. The code didn't check if the 'URL' was actually a URL. It just checked if it was a string, and then handed it to the shell. This is where the syntax of cmd.exe becomes a weapon. By appending command separators like & or |, an attacker can turn a request to open a website into a request to open a website and run ransomware.

The Code: The Smoking Gun

Let's look at the code. This isn't just a theoretical bug; it's a stark example of why input validation is non-negotiable. Before the patch, the openURLMiddleware looked something like this (simplified for dramatic effect):

// VULNERABLE CODE
const openURLMiddleware = async (req, res, next) => {
  const { url } = JSON.parse(req.body);
  // "Sure, I'll open that for you!"
  await open(url);
  res.end('OK');
};

The open() function eventually calls child_process.spawn or exec. If url contains shell metacharacters, they get executed. Now, let's look at the fix in commit 15089907d1f1301b22c72d7f68846a2ef20df547. The maintainers realized they couldn't just trust the string. They needed to validate that it was, in fact, a valid URL protocol.

// FIXED CODE (Commit 15089907d1f1)
async function openURLMiddleware(req, res, next) {
  const { url } = req.body;
  try {
    // 1. Force parsing. If it's not a URL, this throws.
    const parsedUrl = new URL(url);
 
    // 2. Allowlist protocols. No 'file:', no 'javascript:', and definitely no shell hacks.
    if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
       res.writeHead(400); return res.end('Invalid protocol');
    }
  } catch (e) {
    res.writeHead(400); return res.end('Invalid URL');
  }
  await open(url);
  res.end();
}

By enforcing new URL(url), they rely on the WHATWG URL standard to parse the string. If you try to inject http://site.com & calc.exe, the URL parser will either throw an error (invalid character) or URL-encode the malicious parts, rendering them harmless to the shell. It's a robust fix because it validates the structure of the data, not just looking for 'bad characters'.

The Exploit: Popping Calc (and Shells)

So, how do we break it? Imagine you are on a shared network. You run a quick nmap scan and see port 8081 open on a nearby IP. It identifies as the Metro Bundler. It's showtime.

The attack vector is a simple HTTP POST request. You don't need authentication. You don't need cookies. You just need to send JSON.

The Payload:

curl -X POST http://192.168.1.50:8081/open-url \
     -H "Content-Type: application/json" \
     -d '{"url": "http://google.com & calc.exe"}'

When the server processes this on a Windows machine, the constructed command effectively becomes:

cmd /c start http://google.com & calc.exe

The browser opens Google, and moments later, the Calculator app pops up. While calc.exe is the harmless 'Proof of Concept' standard, replace that with a PowerShell one-liner to download a Cobalt Strike beacon, and you own the developer's laptop. The /open-stack-frame endpoint is equally vulnerable, accepting file and lineNumber parameters that are just as susceptible to injection.

The Impact: Why This Hurts

Why is this CVSS 9.8? Because it hits developers where they live. A developer's workstation is the crown jewel of corporate targets. It has SSH keys to production servers. It has AWS credentials in ~/.aws/credentials. It has the source code for the company's proprietary IP. It has VPN access to the internal network.

By compromising one developer via a drive-by Wi-Fi attack or a CSRF attack (if the developer visits a malicious site that fires a request to localhost:8081), an attacker gains a foothold inside the perimeter. From there, lateral movement is trivial. The fact that this requires zero user interaction and zero privileges makes it terrifying. The developer doesn't even see a prompt; the command just executes in the background.

The Fix: Shutting It Down

The immediate fix is to upgrade @react-native-community/cli to version 20.0.0 or later. The React Native team was responsive and the patch is solid. However, relying solely on patching is reactive. We need to talk about defense in depth.

1. Bind to Localhost: There is rarely a good reason for Metro to listen on 0.0.0.0 in a coffee shop. Configure your metro.config.js to bind to 127.0.0.1 unless you explicitly need to debug on a physical device that can't connect via USB.

// metro.config.js
module.exports = {
  server: {
    host: '127.0.0.1'
  }
};

2. Firewall Rules: Developers often disable local firewalls 'to make things work'. Don't. Ensure your OS firewall blocks incoming connections to non-standard ports (like 8081) on public networks. Treat your local dev server like a production server: if it doesn't need to be public, don't make it public.

Official Patches

GitHubCommit fixing the vulnerability by implementing URL validation.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.40%
Top 39% most exploited
5,000
via Shodan

Affected Systems

React Native Development EnvironmentsMetro BundlerWindows Workstations (Primary Target)macOS/Linux Workstations (Secondary Target)

Affected Versions Detail

Product
Affected Versions
Fixed Version
@react-native-community/cli
React Native Community
>= 4.8.0 < 20.0.020.0.0
AttributeDetail
CWE IDCWE-78 (OS Command Injection)
CVSS v3.19.8 (Critical)
Attack VectorNetwork (AV:N)
EPSS Score0.405% (Rising)
Vulnerable ComponentMetro Server Middleware (openURL)
Exploit StatusProof of Concept Available

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.003Command and Scripting Interpreter: Windows Command Shell
Execution
T1203Exploitation for Client Execution
Execution
CWE-78
OS Command Injection

The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command.

Known Exploits & Detection

GitHubPython script demonstrating remote command execution on Windows targets.

Vulnerability Timeline

Patch Committed to GitHub
2025-08-04
Public Disclosure & CVE Assigned
2025-11-03
PoC Released
2025-11-04
Multiple PoCs circulate
2026-01-01

References & Sources

  • [1]JFrog Security Analysis
  • [2]ZeroPath Technical Report

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

•6 minutes ago•CVE-2026-84997
7.5

CVE-2026-84997: Infinite Loop Denial of Service in ReactPHP HTTP Component

An infinite loop vulnerability in ReactPHP's react/http chunked transfer encoding decoder (v0.6.0 up to 1.11.1) allows unauthenticated remote attackers to trigger a denial of service (DoS) by sending crafted chunked requests or responses, completely freezing the single-threaded event loop and pegging CPU usage to 100%.

Alon Barad
Alon Barad
0 views•8 min read
•about 1 hour ago•CVE-2026-88976
6.1

CVE-2026-88976: HTML Deserialization Cross-Site Scripting in @platejs/core

Plate core HTML deserialization APIs parse supplied HTML strings in the active document. When an application passes untrusted or cross-user HTML to these APIs, certain HTML attributes can trigger browser behavior before the HTML is converted into editor nodes.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 2 hours ago•CVE-2026-85999
5.3

CVE-2026-85999: Regular Expression Denial of Service (ReDoS) in Soup Sieve css_parser.py

A polynomial-time Regular Expression Denial of Service (ReDoS) vulnerability in Soup Sieve versions prior to 2.9 allows remote unauthenticated attackers to cause CPU exhaustion and thread-pool denial of service. The vulnerability resides in the trailing whitespace and comment preprocessing step of the CSS parser. An attacker can trigger quadratic backtracking by submitting a crafted CSS selector string containing a long run of internal spaces or comments terminated by a non-matching token. This blocks the Python Global Interpreter Lock (GIL) and halts worker threads.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 3 hours ago•CVE-2026-86000
5.3

CVE-2026-86000: Polynomial-Time Regular Expression Denial of Service in Soup Sieve Selector Parser

A regular expression denial of service (ReDoS) vulnerability in Soup Sieve prior to version 2.9 allows remote attackers to cause CPU exhaustion and service disruption. The issue lies within the definition of the IDENTIFIER and VALUE selector sub-patterns in the CSS parser component, which uses overlapping adjacent quantified groups. When parsing long, crafted, or unclosed CSS selectors, backtracking-based regular expression engines experience quadratic performance degradation. User-controlled selectors can reach this path through soupsieve.compile(), soupsieve.select(), or BeautifulSoup.select(), while applications using only hard-coded selectors are unaffected.

Amit Schendel
Amit Schendel
6 views•7 min read
•about 4 hours ago•CVE-2026-86003
7.5

CVE-2026-86003: Unintended Proxying of DNS UPDATE Requests via Alternative Transports in CoreDNS

A protocol-level validation bypass in CoreDNS versions prior to 1.14.7 allows unauthenticated remote attackers to proxy unauthorized DNS UPDATE messages (Opcode 5) using modern alternative transport layers such as DoH, DoH3, DoQ, and gRPC. If upstream authoritative servers trust the CoreDNS server's source IP and do not enforce TSIG authentication, attackers can inject, alter, or delete DNS zone records, leading to potential zone takeover or traffic redirection.

Alon Barad
Alon Barad
5 views•5 min read
•about 5 hours ago•CVE-2026-72695
8.1

CVE-2026-72695: Authenticated Path Traversal and Arbitrary File Deletion in Grav CMS MediaUploadTrait

A path traversal vulnerability exists in Grav CMS versions prior to 2.0.16. The flaw occurs within the file validation mechanisms of the MediaUploadTrait, enabling authenticated users with media management privileges to bypass sandbox limitations. This allows the deletion of arbitrary files on the filesystem, which can result in denial of service or remote code execution.

Amit Schendel
Amit Schendel
4 views•7 min read