{"record":{"id":"25a82462c3d2d554","repo":"DioxusLabs/dioxus","slug":"protocols-is-an-invalid-header-value","errorCode":null,"errorMessage":"protocols is an invalid header value","messagePattern":"protocols is an invalid header value","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/fullstack/src/payloads/websocket.rs","lineNumber":1261,"sourceCode":"                    HeaderValue::from_static(\"upgrade\"),\n                );\n                headers.insert(\n                    reqwest::header::UPGRADE,\n                    HeaderValue::from_static(\"websocket\"),\n                );\n                headers.insert(\n                    reqwest::header::SEC_WEBSOCKET_KEY,\n                    HeaderValue::from_str(&nonce_value).expect(\"nonce is a invalid header value\"),\n                );\n                headers.insert(\n                    reqwest::header::SEC_WEBSOCKET_VERSION,\n                    HeaderValue::from_static(\"13\"),\n                );\n                if !protocols.is_empty() {\n                    headers.insert(\n                        reqwest::header::SEC_WEBSOCKET_PROTOCOL,\n                        HeaderValue::from_str(&protocols.join(\", \"))\n                            .expect(\"protocols is an invalid header value\"),\n                    );\n                }\n\n                Some(nonce_value)\n            }\n            Version::HTTP_2 => {\n                // TODO: Implement websocket upgrade for HTTP 2.\n                return Err(HandshakeError::UnsupportedHttpVersion(version).into());\n            }\n            _ => {\n                return Err(HandshakeError::UnsupportedHttpVersion(version).into());\n            }\n        };\n\n        // execute request\n        let response = client.execute(request).await?;\n\n        Ok(WebSocketResponse {","sourceCodeStart":1243,"sourceCodeEnd":1279,"githubUrl":"https://github.com/DioxusLabs/dioxus/blob/393d190a801ccb441d41923e232289b4f8a5c669/packages/fullstack/src/payloads/websocket.rs#L1243-L1279","documentation":"The fullstack WebSocket client builds its RFC 6455 handshake manually and writes Sec-WebSocket-Protocol via HeaderValue::from_str(protocols.join(\", \")). from_str rejects any byte outside visible ASCII (control characters, newlines, tabs, and all non-ASCII UTF-8 such as emoji or accented letters), so one malformed subprotocol name makes the expect panic.","triggerScenarios":"Configuring the WebSocket client with .subprotocol(...) entries containing non-ASCII or control characters — newlines, tabs, emoji, non-latin scripts — or programmatically composed protocol strings that embed unvalidated user input.","commonSituations":"Passing auth tokens, locale names, or free-form user strings as subprotocols; copy-pasting protocol names containing invisible unicode; joining protocols that already contain commas/whitespace.","solutions":["Restrict subprotocol names to RFC 6455 token characters: ASCII letters, digits, and - _ . + ~ ! $ & ' ( ) * + , ; = as appropriate tokens","Sanitize/validate protocol strings before passing them to the WebSocket configuration","URL-encode or hash any dynamic value embedded in a protocol name"],"exampleFix":"// before\nws.subprotocol(format!(\"auth-{token}\")); // token contains non-ASCII -> panic\n// after\nws.subprotocol(format!(\"auth-{}\", simple_hash(&token))); // ASCII-only name","handlingStrategy":"validation","validationCode":"fn is_valid_subprotocol(p: &str) -> bool {\n    !p.is_empty()\n        && p.bytes().all(|b| (0x21..=0x7e).contains(&b) && b != b',') // visible ASCII, no delimiter\n        && !p.starts_with(' ')\n}\nassert!(protocols.iter().all(|p| is_valid_subprotocol(p)));","typeGuard":"fn valid_subprotocols<'a>(ps: impl IntoIterator<Item = &'a str>) -> Option<String> {\n    let joined = ps.into_iter().collect::<Vec<_>>().join(\", \");\n    joined.bytes().all(|b| (0x20..=0x7e).contains(&b)).then_some(joined)\n}","tryCatchPattern":null,"preventionTips":["Use fixed ASCII identifiers for subprotocols; never embed raw user input","Hash or base64url-encode dynamic values before using them as protocol names","Validate protocol strings in one place at config-construction time"],"tags":["websocket","http-headers","validation","client","fullstack","panic"],"backgroundTag":null,"analyzedSha":"393d190a801ccb441d41923e232289b4f8a5c669","analyzedAt":"2026-08-16T11:27:45.815Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}