use super::request::{configured, request}; use dever_runtime::{ auth::{CookieOptions, Error, SameSite}, value::secret::Secret, }; fn options() -> CookieOptions { CookieOptions { path: "/".into(), domain: None, max_age: None, same_site: SameSite::Lax, secure: true, http_only: true, } } #[test] fn metadata_guards_secret_values_cookie_origin_and_response_fields() { let service = configured(Some("https://unit.test"), "user.account.verify").unwrap(); let request = request( "POST", &[ ("Host", "unit.test"), ("Origin", "https://unit.test"), ("Cookie", "theme=light; private=v1.c2VjcmV0"), ("X-Test", "value"), ("X-Forwarded-For", "203.0.113.9"), ], ); let (mut context, _) = service .prepare_at( "admin", &request, true, 100, "127.0.0.1:1234".parse().unwrap(), ) .unwrap(); assert_eq!(context.client_address().unwrap(), "127.0.0.1"); assert_eq!(context.request_id().unwrap(), context.request_id().unwrap()); assert_eq!(context.header("X-Test").unwrap().as_deref(), Some("value")); assert_eq!(context.cookie("theme").unwrap().as_deref(), Some("light")); assert!(matches!(context.cookie("private"), Err(Error::Forbidden))); assert!(context.secret_cookie("private").unwrap().is_some()); assert!(context.secret_cookie("theme").unwrap().is_none()); for name in [ "Authorization", "Cookie", "Set-Cookie", "Proxy-Authorization", "X-Api-Key", ] { assert!(context.header(name).is_err()); } for name in [ "Set-Cookie", "Content-Length", "Content-Type", "Connection", "Upgrade", ] { assert!(context.set_header(name, "value").is_err()); } assert!( context .set_header("X-Test", "value\r\nInjected: yes") .is_err() ); assert!(context.set_header("X-Test", &"x".repeat(9000)).is_err()); assert!( context .set_cookie("session", "cannot overwrite provider", options()) .is_err() ); assert!( context .set_cookie("theme", "bad; value", options()) .is_err() ); assert!( context .set_secret_cookie( "private", &Secret::from_input(b"bytes".to_vec()), CookieOptions { secure: false, ..options() } ) .is_err() ); context .set_secret_cookie("private", &Secret::from_input(b"bytes".to_vec()), options()) .unwrap(); assert!( context .set_cookie( "cross", "value", CookieOptions { same_site: SameSite::None, secure: false, ..options() } ) .is_err() ); context.set_header("X-Test", "response").unwrap(); let mut response = dever_runtime::api::response("{}"); context.publish(&mut response); assert!( response .headers() .get_all("set-cookie") .iter() .any(|header| header.as_bytes().starts_with(b"private=v1.Ynl0ZXM;")) ); }