use cookie::{Cookie, CookieBuilder, CookieJar, Key}; fn test_cookie(sometimes: bool) { let always = true; let never = false; // secure set to false let cookie1 = Cookie::build(("name", "value")).secure(false).build(); // $ Alert[rust/insecure-cookie] println!("cookie1 = '{}'", cookie1.to_string()); // secure set to true let cookie2 = Cookie::build(("name", "value")).secure(true).build(); // good println!("cookie2 = '{}'", cookie2.to_string()); // secure left as default (which is `None`, equivalent here to `false`) let cookie3 = Cookie::build(("name", "value")).build(); // $ Alert[rust/insecure-cookie] println!("cookie3 = '{}'", cookie3.to_string()); // secure setting varies (may be false) Cookie::build(("name", "value")).secure(sometimes).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(!sometimes).build(); // $ Alert[rust/insecure-cookie] // with data flow on the "secure" value Cookie::build(("name", "value")).secure(always).build(); // good Cookie::build(("name", "value")).secure(!always).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(never).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(!never).build(); // $ SPURIOUS: Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(always && never).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(always || never).build(); // $ SPURIOUS: Alert[rust/insecure-cookie] // with guards if sometimes { Cookie::build(("name", "value")).secure(sometimes).build(); // $ SPURIOUS: Alert[rust/insecure-cookie] } else { Cookie::build(("name", "value")).secure(sometimes).build(); // $ Alert[rust/insecure-cookie] } // variant uses (all insecure) CookieBuilder::new("name", "value").secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).expires(None).secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).max_age(cookie::time::Duration::hours(12)).secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).domain("example.com").secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).path("/").secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).http_only(true).secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).same_site(cookie::SameSite::Strict).secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).permanent().secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).removal().secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(false).finish(); // $ Alert[rust/insecure-cookie] Cookie::build("name").secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(Cookie::build("name")).secure(false).build(); // $ Alert[rust/insecure-cookie] // edge cases Cookie::build(("name", "value")).secure(true).secure(false).build(); // $ Alert[rust/insecure-cookie] Cookie::build(("name", "value")).secure(false).secure(true).build(); // good // mutable cookie let mut jar = CookieJar::new(); let mut a = Cookie::new("name", "value"); // $ Source jar.add(a.clone()); // $ Alert[rust/insecure-cookie] jar.add_original(a.clone()); // $ Alert[rust/insecure-cookie] a.set_secure(true); jar.add(a.clone()); // good a.set_secure(false); // $ Source jar.add(a.clone()); // $ Alert[rust/insecure-cookie] let key = Key::generate(); let mut signed_jar = jar.signed_mut(&key); let mut b = Cookie::named("name"); // $ Source signed_jar.add(b.clone()); // $ Alert[rust/insecure-cookie] signed_jar.add_original(a.clone()); // $ Alert[rust/insecure-cookie] b.set_secure(sometimes); // $ Source signed_jar.add(b.clone()); // $ Alert[rust/insecure-cookie] b.set_secure(true); signed_jar.add(b.clone()); // good let mut private_jar = jar.private_mut(&key); let mut c = Cookie::from("name"); // $ Source private_jar.add(c.clone()); // $ Alert[rust/insecure-cookie] private_jar.add_original(a.clone()); // $ Alert[rust/insecure-cookie] if sometimes { c.set_secure(true); } private_jar.add(c.clone()); // $ Alert[rust/insecure-cookie] c.set_secure(true); private_jar.add(c.clone()); // $ good let mut d = Cookie::from("name"); // $ Source jar.add(d.clone()); // $ Alert[rust/insecure-cookie] if sometimes { c.set_secure(true); } else { c.set_partitioned(true); } jar.add(d.clone()); // $ SPURIOUS: Alert[rust/insecure-cookie] // parse jar.add(Cookie::parse("name=value; HttpOnly").unwrap()); // $ MISSING: Alert[rust/insecure-cookie] jar.add(Cookie::parse("name=value; Secure; HttpOnly").unwrap()); // good jar.add(Cookie::parse_encoded("name=value; HttpOnly").unwrap()); // $ MISSING: Alert[rust/insecure-cookie] jar.add(Cookie::parse_encoded("name=value; Secure; HttpOnly").unwrap()); // good for cookie in Cookie::split_parse("name1=value1; name2=value2") { jar.add(cookie.unwrap()); // $ MISSING: Alert[rust/insecure-cookie] } for cookie in Cookie::split_parse_encoded("name1=value1; name2=value2") { let mut e = cookie.unwrap(); jar.add(e.clone()); // $ MISSING: Alert[rust/insecure-cookie] e.set_secure(true); jar.add(e.clone()); // good } // partitioned (implies secure) Cookie::build(("name", "value")).partitioned(true).build(); // good } fn test_biscotti() { let mut cookies = biscotti::ResponseCookies::new(); // test set_secure, set_partitioned let a = biscotti::ResponseCookie::new("name", "value"); // $ Source cookies.insert(a.clone()); // $ Alert[rust/insecure-cookie] println!("biscotti1 = {}", a.to_string()); let b = a.set_secure(true); cookies.insert(b.clone()); // good println!("biscotti2 = {}", b.to_string()); let c = b.set_secure(false); // $ Source cookies.insert(c.clone()); // $ Alert[rust/insecure-cookie] println!("biscotti3 = {}", c.to_string()); let d = c.set_partitioned(true); // (implies secure) cookies.insert(d.clone()); // good println!("biscotti4 = {}", d.to_string()); let e = d.set_secure(true); cookies.insert(e.clone()); // good println!("biscotti5 = {}", e.to_string()); let f = e.set_partitioned(false); cookies.insert(f.clone()); // good println!("biscotti6 = {}", f.to_string()); let g = f.set_secure(false); // $ Source cookies.insert(g.clone()); // $ Alert[rust/insecure-cookie] println!("biscotti7 = {}", g.to_string()); // variant creation (insecure) let h = biscotti::ResponseCookie::from(("name", "value")); // $ Source cookies.insert(h); // $ Alert[rust/insecure-cookie] // variant uses (all insecure) let i = biscotti::ResponseCookie::new("name", "value"); // $ Source cookies.insert(i.clone().set_name("name2")); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_value("value2")); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_http_only(true)); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_same_site(biscotti::SameSite::Strict)); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_max_age(None)); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_path("/")); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().unset_path()); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_domain("example.com")); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().unset_domain()); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().set_expires(None)); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().unset_expires()); // $ Alert[rust/insecure-cookie] cookies.insert(i.clone().make_permanent()); // $ Alert[rust/insecure-cookie] } fn test_qhelp_examples() { { // BAD: creating a cookie without specifying the `secure` attribute let cookie = Cookie::build(("session", "abcd1234")).build(); // $ Alert[rust/insecure-cookie] let mut jar = cookie::CookieJar::new(); jar.add(cookie.clone()); } { // GOOD: set the `CookieBuilder` 'Secure' attribute so that the cookie is only sent over HTTPS let secure_cookie = Cookie::build(("session", "abcd1234")).secure(true).build(); let mut jar = cookie::CookieJar::new(); jar.add(secure_cookie.clone()); // GOOD: alternatively, set the 'Secure' attribute on an existing `Cookie` let mut secure_cookie2 = Cookie::new("session", "abcd1234"); secure_cookie2.set_secure(true); jar.add(secure_cookie2); } } fn test_actix_web() { // actix-web re-exports the cookie crate use actix_web::cookie::Cookie as ActixCookie; let mut jar = actix_web::cookie::CookieJar::new(); // secure set to false ActixCookie::build("name", "value").secure(false).finish(); // $ Alert[rust/insecure-cookie] ActixCookie::build("name", "value").secure(false).path("/").finish(); // $ Alert[rust/insecure-cookie] let mut cookie1 = ActixCookie::new("name", "value"); cookie1.set_secure(false); // $ Source jar.add(cookie1.clone()); // $ Alert[rust/insecure-cookie] // secure set to true ActixCookie::build("name", "value").secure(true).finish(); // good let mut cookie2 = ActixCookie::new("name", "value"); cookie2.set_secure(true); // good jar.add(cookie2.clone()); // secure left as default ActixCookie::build("name", "value").finish(); // $ Alert[rust/insecure-cookie] let cookie3 = ActixCookie::new("name", "value"); // $ Source jar.add(cookie3.clone()); // $ Alert[rust/insecure-cookie] // secure reset to None cookie2.set_secure(None); // $ Source jar.add(cookie2.clone()); // $ Alert[rust/insecure-cookie] } fn test_poem() { use poem::web::cookie::Cookie as PoemCookie; let mut jar = poem::web::cookie::CookieJar::default(); // secure set to false let mut cookie1 = PoemCookie::new_with_str("name", "value"); cookie1.set_secure(false); // $ Source jar.add(cookie1.clone()); // $ Alert[rust/insecure-cookie] // secure set to true let mut cookie2 = PoemCookie::new_with_str("name", "value"); cookie2.set_secure(true); // good jar.add(cookie2.clone()); // secure left as default (which is `true` for Poem) let cookie3 = PoemCookie::new_with_str("name", "value"); jar.add(cookie3.clone()); // good // set secure via CookieConfig let cookie_config_bad = poem::session::CookieConfig::new().secure(false); // $ Source _ = poem::session::ServerSession::new(cookie_config_bad, ()); // $ Alert[rust/insecure-cookie] let cookie_config_bad2 = poem::session::CookieConfig::new().secure(false).name("name").path("/"); // $ Source _ = poem::session::ServerSession::new(cookie_config_bad2, ()); // $ Alert[rust/insecure-cookie] let cookie_config_good = poem::session::CookieConfig::new().secure(true); _ = poem::session::ServerSession::new(cookie_config_good, ()); // good let cookie_config_default = poem::session::CookieConfig::new(); _ = poem::session::ServerSession::new(cookie_config_default, ()); // good } fn test_http_types() { use http_types::Cookie as HttpTypesCookie; let mut jar = http_types::cookies::CookieJar::default(); // secure set to false HttpTypesCookie::build("name", "value").secure(false).finish(); // $ Alert[rust/insecure-cookie] HttpTypesCookie::build("name", "value").secure(false).path("/").finish(); // $ Alert[rust/insecure-cookie] let mut cookie1 = HttpTypesCookie::new("name", "value"); cookie1.set_secure(false); // $ Source jar.add(cookie1.clone()); // $ Alert[rust/insecure-cookie] // secure set to true HttpTypesCookie::build("name", "value").secure(true).finish(); // good let mut cookie2 = HttpTypesCookie::new("name", "value"); cookie2.set_secure(true); // good jar.add(cookie2.clone()); // secure left as default HttpTypesCookie::build("name", "value").finish(); // $ Alert[rust/insecure-cookie] let cookie3 = HttpTypesCookie::new("name", "value"); // $ Source jar.add(cookie3.clone()); // $ Alert[rust/insecure-cookie] // secure reset to None cookie2.set_secure(None); // $ Source jar.add(cookie2.clone()); // $ Alert[rust/insecure-cookie] } fn main() { test_cookie(true); test_cookie(false); test_biscotti(); test_qhelp_examples(); test_actix_web(); test_poem(); test_http_types(); }