{"record":{"id":"b9e5d6f9f1f0bda4","repo":"BigPizzaV3/CodexPlusPlus","slug":"cdp-websocket-port-port-does-not-match-debug-por","errorCode":null,"errorMessage":"CDP WebSocket port {port} does not match debug port {expected_port}","messagePattern":"CDP WebSocket port (.+?) does not match debug port (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/cdp.rs","lineNumber":231,"sourceCode":"    if !matches!(parsed.scheme(), \"ws\" | \"wss\") {\n        bail!(\"CDP WebSocket URL must use ws or wss\");\n    }\n    let host = parsed\n        .host_str()\n        .ok_or_else(|| anyhow::anyhow!(\"CDP WebSocket URL has no host\"))?;\n    let address = host\n        .trim_start_matches('[')\n        .trim_end_matches(']')\n        .parse::<IpAddr>()\n        .with_context(|| \"CDP WebSocket host must be a loopback IP address\")?;\n    if !address.is_loopback() {\n        bail!(\"CDP WebSocket host must be loopback\");\n    }\n    let port = parsed\n        .port()\n        .ok_or_else(|| anyhow::anyhow!(\"CDP WebSocket URL must include an explicit port\"))?;\n    if port != expected_port {\n        bail!(\"CDP WebSocket port {port} does not match debug port {expected_port}\");\n    }\n    Ok(())\n}\n\npub fn pick_page_target(targets: &[CdpTarget]) -> anyhow::Result<CdpTarget> {\n    let mut first_page = None;\n    for target in targets\n        .iter()\n        .filter(|target| is_injectable_page_target(target))\n    {\n        first_page.get_or_insert(target);\n        if is_primary_codex_page_target(target) {\n            return Ok(target.clone());\n        }\n    }\n\n    if let Some(target) = first_page {\n        return Ok(target.clone());","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/cdp.rs#L213-L249","documentation":"CodexPlusPlus hardens CDP target discovery: every webSocketDebuggerUrl returned by the browser must use ws/wss, point at a loopback IP, carry an explicit port, and that port must equal the debug port used to fetch the target list (validate_cdp_websocket_url in crates/codex-plus-core/src/cdp.rs). This error means the WebSocket URL embedded in a CDP target carries a different port than the port you queried, so the library refuses the connection as a possible SSRF/redirect to another debugger endpoint.","triggerScenarios":"Calling query_targets_url(client, http-URL-on-port-P, P) or validate_cdp_websocket_url(url, expected_port) directly where target.web_socket_debugger_url carries another port: the browser was relaunched and picked a new ephemeral --remote-debugging-port, a cached target list from an older browser instance is reused, or a port-mapped setup (container 9222 published as host 9223) makes the ws URL port differ from the host-side port.","commonSituations":"Chrome/Chromium restarted without a fixed debug port; Docker port-publish remapping the devtools port; a proxy rewriting host or port; tests mixing a targets list fetched from port A with validation against port B.","solutions":["Re-query the /json target list from the exact same port you pass as debug_port so both sides agree","Launch the browser with a fixed port, e.g. --remote-debugging-port=9222, and use 9222 everywhere","In port-mapped setups (Docker, SSH forwards) run validation from inside the same network namespace, or validate against the port the ws URL actually uses","Discard cached CdpTarget lists whenever the browser process restarts"],"exampleFix":"// before: list fetched from one port, validated against another\nlet targets = query_targets_url(&client, &list_url, old_debug_port).await?;\n// after: derive list URL and expected port from one value\nlet debug_port = 9222;\nlet list_url = format!(\"http://127.0.0.1:{debug_port}/json\");\nlet targets = query_targets_url(&client, &list_url, debug_port).await?;","handlingStrategy":"validation","validationCode":"let parsed = reqwest::Url::parse(websocket_url)?;\nif parsed.port() != Some(debug_port) {\n    // re-query /json from this exact port before connecting\n    targets = query_targets_url(&client, &list_url_on(debug_port), debug_port).await?;\n}","typeGuard":null,"tryCatchPattern":"match validate_cdp_websocket_url(url, debug_port) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"does not match debug port\") => { targets = requery_targets(debug_port).await?; }\n    Err(e) => return Err(e),\n}","preventionTips":["Derive the list URL and the expected port from one variable","Launch the browser with a fixed --remote-debugging-port","Drop cached target lists when the browser process restarts"],"tags":["cdp","chrome-devtools","websocket","ssrf-protection","port-mismatch"],"backgroundTag":"cdp-port-mismatch","analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}