Back to Blog
2026-04-03

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

ACTIVE CAMPAIGN: CVSS 10.0 — 766 Servers Compromised 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:

  1. Reconnaissance: Identify Next.js apps using the App Router (often exposed via headers or specific routing patterns)
  2. Payload delivery: Send crafted requests to React Server Component endpoints
  3. Deserialization abuse: Exploit the deserialization of server component data to inject executable code
  4. Post-exploitation: Deploy the NEXUS Listener framework for systematic credential harvesting
766
Servers compromised in 24 hours
10.0
CVSS Base Score (Critical)
6 Types
Credentials targeted (DB, SSH, AWS, Stripe, GitHub, Shell)
UAT-10608
Threat actor designation by Cisco Talos

🎯 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_ed25519 and 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_history containing 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:

  1. Patch NOW: Upgrade to Next.js 14.2.0 or later
  2. Audit credentials: Assume environment variables are compromised
  3. Monitor access logs: AWS, GitHub, Stripe, database—all of them
  4. 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 →
Share this: