The React2Shell Campaign: How CVE-2025-55182 Harvested Credentials from 766 Next.js Servers in 24 Hours
On April 3, 2026, Cisco Talos revealed UAT-10608's automated credential harvesting operation exploiting CVE-2025-55182. 766 servers breached in 24 hours. Here's how to defend against React2Shell attacks.
The React2Shell Campaign: How CVE-2025-55182 Harvested Credentials from 766 Next.js Servers in 24 Hours
At 09:00 UTC on April 3, 2026, Cisco Talos published a report that should terrify anyone running Next.js applications. A threat actor tracked as UAT-10608 had been operating an automated credential harvesting campaign, exploiting CVE-2025-55182—a critical remote code execution vulnerability in React Server Components—to breach 766 servers in a single 24-hour window.
The payload wasn't ransomware. It wasn't data exfiltration for sale. It was systematic, industrial-scale credential harvesting: database passwords, SSH private keys, AWS access tokens, Stripe API keys, GitHub personal access tokens, and shell command history. Everything needed to pivot from a single compromised Next.js app to complete infrastructure takeover.
Case Study: The NEXUS Listener Dashboard
Talos researchers observed UAT-10608's command-and-control infrastructure included a dashboard labeled "NEXUS Listener" that displayed real-time statistics of compromised hosts. The interface tracked: total compromised servers, credential types extracted per host, and geographic distribution. Attackers weren't just breaching servers—they were managing the operation like an enterprise SaaS platform. This wasn't opportunistic scanning. It was organized, automated, and devastatingly effective.
🔍 Understanding CVE-2025-55182: The React2Shell Vulnerability
CVE-2025-55182 affects React Server Components (RSC) and the Next.js App Router. It's the kind of vulnerability that only exists because modern JavaScript frameworks have become so complex that their boundaries blur.
The flaw exists in how React Server Components deserialize data from the server to the client. When Next.js processes server component payloads, insufficient input validation allows attackers to inject serialized objects that execute arbitrary code during deserialization. CVSS 10.0. Remote. Unauthenticated. Game over.
The attack vector is deceptively simple:
- Reconnaissance: Identify Next.js apps using the App Router (often exposed via headers or specific routing patterns)
- Payload delivery: Send crafted requests to React Server Component endpoints
- Deserialization abuse: Exploit the deserialization of server component data to inject executable code
- Post-exploitation: Deploy the NEXUS Listener framework for systematic credential harvesting
🎯 What Attackers Actually Extracted
UAT-10608 wasn't merely defacing websites or cryptojacking. The threat actor operated a professional credential harvesting pipeline targeting the keys to enterprise infrastructure.
According to the Talos report, automated scripts extracted:
- Database credentials: Connection strings in environment variables and config files
- SSH private keys:
~/.ssh/id_rsa,~/.ssh/id_ed25519and custom-named keys - AWS secrets: IAM access keys and session tokens from
~/.aws/and environment variables - Stripe API keys: Live and test keys from application configurations
- GitHub tokens: Personal access tokens with repository or org-wide permissions
- Shell command history:
.bash_history,.zsh_historycontaining password leaks
This is the credential sprawl apocalypse. One compromised Next.js app exposes your entire cloud infrastructure.
The Pivot Problem
Most organizations treat web app compromises as isolated incidents. But with harvested SSH keys and AWS tokens, UAT-10608 pivoted from Next.js containers to underlying hosts, database servers, and cloud control planes. Your React vulnerability became your full infrastructure breach.
🛡️ Immediate Defense: Detection & Response
If you're running Next.js applications, you need answers now. Here's a rapid assessment script to check your exposure.
#!/usr/bin/env python3
"""
CVE-2025-55182 Exposure Scanner for Next.js Applications
Checks for indicators of compromise and vulnerable configurations
"""
import os
import subprocess
import sys
from pathlib import Path
def check_nextjs_version():
"""Check if Next.js version is patched"""
try:
result = subprocess.run(
['npm', 'list', 'next', '--json'],
capture_output=True, text=True
)
if '14.2.0' in result.stdout or '15.x' in result.stdout:
return True, "Version may be patched (14.2.0+ or 15.x+)"
elif '14.1' in result.stdout or '13.' in result.stdout:
return False, "VULNERABLE: Next.js <14.2.0 detected"
return None, "Unable to determine version"
except Exception as e:
return None, f"Check failed: {e}"
def scan_for_credential_leaks():
"""Scan for leaked credentials in shell history and logs"""
high_risk_patterns = [
'AKIA', # AWS Access Key ID prefix
'ghp_', # GitHub Personal Access Token
'sk_live', # Stripe live key
'PRIVATE KEY',
'DATABASE_URL',
]
findings = []
check_paths = [
Path.home() / '.bash_history',
Path.home() / '.zsh_history',
Path('/var/log'),
]
for path in check_paths:
if path.exists() and path.is_file():
try:
with open(path, 'r', errors='ignore') as f:
content = f.read()
for pattern in high_risk_patterns:
if pattern in content:
findings.append(f"Found '{pattern}' in {path}")
except:
pass
return findings
def main():
print("🔍 CVE-2025-55182 Post-Incident Assessment\n")
print("=" * 50)
# Check Next.js version
patched, msg = check_nextjs_version()
status = "✅" if patched else "⚠️ " if patched is False else "❓"
print(f"\n{status} Next.js Version Check: {msg}")
# Scan for credentials
print("\n🕵️ Scanning for credential leaks in history files...")
leaks = scan_for_credential_leaks()
if leaks:
print("⚠️ POTENTIAL LEAKS DETECTED:")
for leak in leaks:
print(f" - {leak}")
else:
print("✅ No obvious credential patterns found in history files")
print("\n" + "=" * 50)
print("Next steps:")
print("1. Upgrade Next.js to 14.2.0+ immediately")
print("2. Rotate ALL credentials in environment variables")
print("3. Check AWS/GitHub/Stripe access logs for unauthorized access")
print("4. Review container and host SSH key permissions")
if __name__ == '__main__':
main()
Run this on every server hosting Next.js applications. Do not assume you're safe because you weren't in the 766. UAT-10608's infrastructure shows this is an ongoing campaign with automated tooling.
🔐 Preventing Credential Harvesting: Defense in depth
Even if you patch CVE-2025-55182 tomorrow, you're still vulnerable if credentials are extractable from compromised containers. Here's how to break the kill chain:
1. Runtime Secret Protection
Never store credentials in files readable by the application user. Use runtime secret injection:
# docker-compose.yml - WRONG
environment:
DATABASE_URL: "postgres://admin:secret123@db:5432/app"
# docker-compose.yml - BETTER: Use secrets
secrets:
db_password:
file: ./secrets/db_password.txt
services:
app:
secrets:
- db_password
environment:
DATABASE_URL_FILE: /run/secrets/db_password
2. Network Segmentation
Assume your Next.js container will be compromised. Limit the blast radius:
# Block container access to cloud metadata APIs
iptables -A OUTPUT -d 169.254.169.254 -j DROP
# Block container-to-container lateral movement
iptables -A OUTPUT -p tcp --dport 22 -j DROP
3. Credential Lifecycle
Implement short-lived credentials. AWS IAM Roles for Service Accounts (IRSA), HashiCorp Vault dynamic secrets, or cloud-native workload identity. If a key is extracted, it should be useless in 15 minutes.
4. File System Hardening
Prevent credential scanning by restricting file access:
# Dockerfile
RUN chmod 700 /root/.ssh && \
chmod 600 /root/.ssh/* && \
rm -f /root/.bash_history /root/.zsh_history && \
ln -sf /dev/null /root/.bash_history
⚡ The Bottom Line
CVE-2025-55182 isn't just another JavaScript framework vulnerability. It's a supply chain weapon that turns React Server Components into infrastructure-breaching missiles. The UAT-10608 campaign proves that attackers have industrialized post-exploitation credential harvesting—766 servers in 24 hours is not manual work.
If you're running Next.js:
- Patch NOW: Upgrade to Next.js 14.2.0 or later
- Audit credentials: Assume environment variables are compromised
- Monitor access logs: AWS, GitHub, Stripe, database—all of them
- Implement runtime detection: Container credential access patterns
The React2Shell campaign is active. The only question is whether you'll be in next week's statistics.
Sanitize .env Files Before Sharing
Need to share environment variables? Use Env Sanitizer to automatically detect and mask secrets. All processing happens client-side—your data never leaves your browser.
Open Env Sanitizer →