How to Fix & Prevent React2Shell Attack on Next.js

On December 3, 2025, React2Shell dropped - a CVSS 10.0 vulnerability letting attackers run any code on your Next.js server. No login needed. Within hours, state-sponsored groups were exploiting it.
This guide shows exactly how I secured a production app, with commands you can copy-paste.
TL;DR - Quick Fix
If you're in a hurry, run this now:
# Check if you're vulnerable
npm list next
# Fix it
npx fix-react2shell-next
# Verify
npx fix-react2shell-next
# Should say: "Your Next.js installation is not vulnerable"
Then read the rest of this guide because patching alone isn't enough.
Am I Affected?
Quick check:
- Using App Router? (files in
/appdirectory) → Potentially vulnerable - Using Pages Router only? (files in
/pagesdirectory) → Safe - Static export? (no server) → Safe
- Next.js 13.x or 14.x stable? → Safe
Vulnerable versions:
| Version | Patch to |
|---|---|
| 15.0.x | 15.0.5+ |
| 15.1.x | 15.1.9+ |
| 15.2.x | 15.2.6+ |
| 15.3.x | 15.3.6+ |
| 15.4.x | 15.4.8+ |
| 15.5.x | 15.5.7+ |
| 16.0.x | 16.0.7+ |
Full details: Next.js Security Advisory
What's the Actual Risk?
React2Shell exploits a flaw in how React Server Components handle incoming data. An attacker sends a malformed request, and your server executes their code.
What attackers can do:
- Read your environment variables (API keys, database passwords)
- Access your database
- Pivot to other systems on your network
- Install crypto miners or backdoors
For the technical deep-dive: Datadog's analysis or Wiz's breakdown.
Step 1: Patch Now
The critical fix. Do this first.
# Option A: Use the official tool
npx fix-react2shell-next
# Option B: Manual upgrade
npm install next@15.5.7 # or latest in your branch
Verify it worked:
npx fix-react2shell-next
# Expected: "Your Next.js installation is not vulnerable to CVE-2025-55182"
Step 2: Scan for Compromise
Before assuming you're safe, check if you were already exploited.
Assetnote's scanner can detect vulnerable instances:
# Clone and install
git clone https://github.com/assetnote/react2shell-scanner
cd react2shell-scanner
pip install -r requirements.txt
# Safe scan (no code execution on target)
python3 scanner.py -u https://your-app.com --safe-check
Check your logs for:
- Unusual POST requests to
/_next/paths - Multipart requests to non-upload endpoints
- Spikes in 500 errors
Step 3: Hide Your Tech Stack
Attackers scan for Next.js servers by checking response headers. Remove the fingerprints.
In next.config.ts:
const nextConfig: NextConfig = {
headers: async () => [
{
source: '/(.*)',
headers: [
{ key: 'X-Powered-By', value: '' },
{ key: 'Server', value: '' }
],
},
],
};
If using a reverse proxy (Nginx/Caddy):
# Nginx
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
# Caddy
servers {
headers {
-Server
-X-Powered-By
}
}
Verify:
curl -I https://your-app.com 2>/dev/null | grep -E "Server:|X-Powered-By:"
# Should return nothing
Step 4: Rotate All Secrets
This is the step most people skip. Don't.
Even if you patched quickly, your secrets may have been stolen during the vulnerability window. Assume breach.
What to rotate:
| Category | Examples |
|---|---|
| Database | Connection strings, passwords |
| APIs | Stripe, OpenAI, Mailjet, Vimeo |
| Auth | JWT secrets, session keys |
| CMS | Admin tokens, API keys |
| Webhooks | Signing secrets |
Rotation process:
- Generate new credentials in service dashboard
- Update
.env.production - Deploy with new credentials
- Verify the app works
- Then revoke old credentials
Quick validation script:
// test-credentials.ts
async function test(name: string, fn: () => Promise<boolean>) {
try {
const ok = await fn();
console.log(ok ? `✓ ${name}` : `⚠ ${name}: Check permissions`);
} catch (e) {
console.log(`✗ ${name}: ${e.message}`);
process.exit(1);
}
}
// Add tests for each service
await test('Database', async () => {
// Your DB connection test
return true;
});
await test('Stripe', async () => {
const res = await fetch('https://api.stripe.com/v1/balance', {
headers: { Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}` }
});
return res.ok;
});
Run after each deployment: npx tsx test-credentials.ts
Step 5: Lock Down API Access
Where possible, restrict your API keys:
- Use restricted keys - Stripe, for example, lets you create keys with specific permissions only
- IP allowlisting - Some services let you restrict API access to your server IPs
- VPN for admin panels - Put sensitive dashboards behind a VPN
Step 6: Fix Container Permissions
If you're running Docker, check your file permissions. Common issue: upload directories owned by wrong user.
# Set correct ownership (adjust path and UID for your setup)
sudo chown -R 1000:1000 /var/data/uploads
sudo find /var/data/uploads -type d -exec chmod 755 {} \;
sudo find /var/data/uploads -type f -exec chmod 644 {} \;
Add this to your deployment script so it runs automatically.
Verification Checklist
Run through this after remediation:
# 1. Version check
npm list next
# Should show patched version
# 2. Official verification
npx fix-react2shell-next
# Should say "not vulnerable"
# 3. Header check
curl -I https://your-app.com | grep -E "Server:|X-Powered-By:"
# Should return nothing
# 4. Credential test
npx tsx test-credentials.ts
# All should pass
Copy-Paste Checklist
Save this for your incident response:
Immediate (Do Now)
-
npx fix-react2shell-next - Verify:
npm list nextshows patched version - Check logs for exploitation attempts
Today
- Hide server headers (Next.js config + reverse proxy)
- Scan with react2shell-scanner
- Start secret rotation
This Week
- Complete all secret rotations
- Revoke old credentials (after verifying new ones work)
- Review container permissions
- Set up log monitoring for suspicious patterns
- Restrict API keys where possible
Key Lessons
-
Patch fast, but don't stop there - The patch fixes the vulnerability, but doesn't undo any damage from the exposure window.
-
Assume breach - When a CVSS 10.0 exploit goes public, assume attackers tried it on you. Rotate secrets.
-
Layer your defenses - Hide server signatures, restrict API access, monitor logs. No single control is enough.
-
Automate verification - Write scripts to test credentials and security controls. Run them in CI/CD.
-
Stay informed - Follow Next.js blog, GitHub Security Advisories, and your framework's security channels.
Questions? Reach out on Twitter @ssv445 or LinkedIn.