{"id":"57daefdab67a0ae0","repo":"actix/actix-web","slug":"invalid-header-value","errorCode":null,"errorMessage":"Invalid header value","messagePattern":"Invalid header value","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"actix-web/src/middleware/default_headers.rs","lineNumber":94,"sourceCode":"    #[doc(hidden)]\n    #[deprecated(\n        since = \"4.0.0\",\n        note = \"Prefer `.add((key, value))`. Will be removed in v5.\"\n    )]\n    pub fn header<K, V>(self, key: K, value: V) -> Self\n    where\n        HeaderName: TryFrom<K>,\n        <HeaderName as TryFrom<K>>::Error: Into<HttpError>,\n        HeaderValue: TryFrom<V>,\n        <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,\n    {\n        self.add((\n            HeaderName::try_from(key)\n                .map_err(Into::into)\n                .expect(\"Invalid header name\"),\n            HeaderValue::try_from(value)\n                .map_err(Into::into)\n                .expect(\"Invalid header value\"),\n        ))\n    }\n\n    /// Adds a default *Content-Type* header if response does not contain one.\n    ///\n    /// Default is `application/octet-stream`.\n    pub fn add_content_type(self) -> Self {\n        #[allow(clippy::declare_interior_mutable_const)]\n        const HV_MIME: HeaderValue = HeaderValue::from_static(\"application/octet-stream\");\n        self.add((CONTENT_TYPE, HV_MIME))\n    }\n}\n\nimpl<S, B> Transform<S, ServiceRequest> for DefaultHeaders\nwhere\n    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,\n    S::Future: 'static,\n{","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/actix/actix-web/blob/937960ca67f20e14ffe2a075bf6d4593502be12c/actix-web/src/middleware/default_headers.rs#L76-L112","documentation":"The deprecated `DefaultHeaders::header()` helper at actix-web/src/middleware/default_headers.rs:92-95 converts the value with `HeaderValue::try_from` and `.expect(\"Invalid header value\")`. Values containing illegal bytes (e.g. control characters, a raw newline `\\n`) panic.","triggerScenarios":"Calling `.header(\"X-Test\", \"\\n\")` or passing user input containing CR/LF or other forbidden bytes.","commonSituations":"Embedding untrusted strings into a header value without sanitization (header injection risk).","solutions":["Use the `.add((name, value))` API and validate the value first, handling the error.","Strip or reject CR/LF and other control bytes from any dynamic value.","For ASCII-only values, consider percent-encoding or base64-encoding binary data."],"exampleFix":"// before\nmw.header(\"X-Test\", user_input); // panics if user_input has \\n\n\n// after\nfn try_add(mw: DefaultHeaders, v: &str) -> Result<DefaultHeaders, actix_web::Error> {\n    let val = HeaderValue::try_from(v)?;\n    Ok(mw.add((\"X-Test\", val)))\n}","handlingStrategy":"validation","validationCode":"// Validate header values; reject CR/LF and control bytes.\nuse actix_web::http::header::HeaderValue;\nfn valid_value(v: &str) -> bool {\n    HeaderValue::try_from(v).is_ok()\n}\n// assert!(!valid_value(\"\\n\"));\n// assert!(valid_value(\"ok\"));","typeGuard":"fn is_valid_header_value(v: &str) -> bool {\n    !v.bytes().any(|b| b == b'\\r' || b == b'\\n' || b.is_ascii_control())\n        && HeaderValue::try_from(v).is_ok()\n}","tryCatchPattern":null,"preventionTips":["Migrate to .add((name, value)) and handle the Result.","Sanitize untrusted strings before placing them in headers (prevents injection)."],"tags":["rust","actix","actix-web","middleware","runtime","panic","deprecated","headers","security"],"analyzedSha":"937960ca67f20e14ffe2a075bf6d4593502be12c","analyzedAt":"2026-08-06T01:15:46.978Z","schemaVersion":2}