{"record":{"id":"0be103ed9f605be1","repo":"hasura/graphql-engine","slug":"invalid-header-name-0","errorCode":null,"errorMessage":"Invalid header name: {0}","messagePattern":"Invalid header name: (.+?)","errorType":"exception","errorClass":"ConnectionInitError","httpStatus":null,"severity":"error","filePath":"v3/crates/graphql/graphql-ws/src/protocol/init.rs","lineNumber":122,"sourceCode":"                            let session = authorize_identity(&auth_response.identity, &headers)?;\n                            Ok((session, headers))\n                        }\n                        ConnectionInitState::Initialized { .. } => {\n                            Err(ConnectionInitError::AlreadyInitialized)\n                        }\n                    }\n                })\n            },\n        )\n        .await\n}\n\n/// Error types that may occur during connection initialization.\n#[derive(Debug, thiserror::Error)]\npub enum ConnectionInitError {\n    #[error(\"Connection already initialized\")]\n    AlreadyInitialized,\n    #[error(\"Invalid header name: {0}\")]\n    InvalidHeaderName(#[from] http::header::InvalidHeaderName),\n    #[error(\"Invalid header value: {0}\")]\n    InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),\n    #[error(\"AuthError: {0}\")]\n    Authn(#[from] AuthError),\n    #[error(\"SessionError: {0}\")]\n    Session(#[from] SessionError),\n}\n\nimpl tracing_util::TraceableError for ConnectionInitError {\n    fn visibility(&self) -> tracing_util::ErrorVisibility {\n        tracing_util::ErrorVisibility::User\n    }\n}\n\n/// Parses headers from a given map of strings into an `http::HeaderMap`.\n/// Returns a parsed header map or an error if the headers are invalid.\nfn parse_headers(map: HashMap<String, String>) -> Result<http::HeaderMap, ConnectionInitError> {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/graphql/graphql-ws/src/protocol/init.rs#L104-L140","documentation":"ConnectionInitError::InvalidHeaderName wraps http::header::InvalidHeaderName and occurs when a header name supplied during graphql-ws connection initialization is not syntactically valid. HTTP/1 header names must be valid HTTP tokens (no spaces, control characters, or non-token separators), so headers derived from connection_init payload parameters fail validation when malformed.","triggerScenarios":"The connection_init handshake attempts to build HTTP headers (e.g. forwarding auth or custom headers from the init payload) and a header name contains invalid characters — spaces, colons, CR/LF, or non-ASCII — causing HeaderName::from_str / try_from to fail during init.","commonSituations":"Client-supplied header maps in the connection_init payload with names like 'X My Header' or 'Authorization:'; headers configured via env/config strings with trailing whitespace or newlines; forwarding arbitrary user input as header names without validation; injecting full 'Name: value' strings as the name field.","solutions":["Fix the header name to a valid HTTP token (letters, digits, and - _ . ~ ! # $ & ' * + ^ ` |), e.g. 'X-My-Header'","Validate/normalize header names before putting them into the connection_init payload; pass values separately, never 'Name: value' combined","Sanitize configuration strings (trim whitespace/newlines) when headers come from env vars or config files","If forwarding arbitrary metadata, use a fixed header name and put variable data in the value"],"exampleFix":"// before\n{\"type\":\"connection_init\",\"payload\":{\"headers\":{\"X Custom: id\":\"abc\"}}}\n\n// after\n{\"type\":\"connection_init\",\"payload\":{\"headers\":{\"x-custom-id\":\"abc\"}}}","handlingStrategy":"validation","validationCode":"fn valid_header_name(name: &str) -> bool {\n    !name.is_empty()\n        && name.bytes().all(|b| match b {\n            b'!' | b'#' | b'$' | b'%' | b'&' | b'\\'' | b'*' | b'+' | b'-' | b'.'\n            | b'^' | b'_' | b'`' | b'|' | b'~' => true,\n            b if b.is_ascii_alphanumeric() => true,\n            _ => false,\n        })\n}","typeGuard":"fn is_valid_header_name(name: &str) -> bool {\n    http::header::HeaderName::try_from(name).is_ok()\n}","tryCatchPattern":"match ws_conn.initialize_with_headers(payload, headers).await {\n    Err(ConnectionInitError::InvalidHeaderName(e)) => {\n        respond_bad_request(format!(\"invalid header name: {e}\"));\n    }\n    Err(e) => respond_init_error(e),\n    Ok(()) => (),\n}","preventionTips":["Whitelist/validate client-supplied header names in the connection_init payload","Never pass 'Name: value' strings as header names; split them first","Trim whitespace and reject control characters in header config from env/config files"],"tags":["rust","graphql","websocket","http-headers","header-validation"],"backgroundTag":"invalid-http-header","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}