{"record":{"id":"1b4d7ff33d97c635","repo":"BigPizzaV3/CodexPlusPlus","slug":"cdp-websocket-url-must-use-ws-or-wss","errorCode":null,"errorMessage":"CDP WebSocket URL must use ws or wss","messagePattern":"CDP WebSocket URL must use ws or wss","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/cdp.rs","lineNumber":214,"sourceCode":"\n    let targets = response\n        .json::<Vec<CdpTarget>>()\n        .await\n        .context(\"failed to deserialize CDP targets\")?;\n    for target in &targets {\n        if let Some(websocket_url) = target.web_socket_debugger_url.as_deref() {\n            validate_cdp_websocket_url(websocket_url, debug_port).with_context(|| {\n                format!(\"unsafe CDP target WebSocket URL for target {}\", target.id)\n            })?;\n        }\n    }\n    Ok(targets)\n}\n\npub fn validate_cdp_websocket_url(url: &str, expected_port: u16) -> anyhow::Result<()> {\n    let parsed = reqwest::Url::parse(url).context(\"invalid CDP WebSocket URL\")?;\n    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    }","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/cdp.rs#L196-L232","documentation":"Security guard in validate_cdp_websocket_url: the DevTools WebSocket URL returned by the browser or a target uses a scheme other than ws/wss (e.g. http), so it cannot be a valid WebSocket endpoint and is rejected before connecting. The offending input is the URL string from the CDP response.","triggerScenarios":"Thrown at crates/codex-plus-core/src/cdp.rs:214 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use the webSocketDebuggerUrl as returned by the CDP endpoint unmodified","Check for proxies/rewriters mangling the returned URL","Update the browser if it returns malformed DevTools URLs"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}