Problem
In ChainCookies::store, the MAX_COOKIE_BYTES refusal at src/cookies.rs:170 runs before the expired branch at :183. A cookie deletion costs no memory and no wire bytes, so the per-cookie size ceiling should not gate it. As written, an oversized Set-Cookie carrying Max-Age=0 is dropped, and the stale cookie stays in the store and keeps going out on later hops:
held before: Some("s=realsessionvalue")
Set-Cookie: s=<5000 x's>; Max-Age=0
held after: Some("s=realsessionvalue") // expected None
The real trigger is frameworks that log out by re-sending the cookie's full value with Max-Age=0 rather than blanking it. A 4 KB JWT or SAML session cookie does exactly that.
Same shape as the ordering mistake #88 fixed one branch below, where the incumbent was dropped before the budget check could refuse the replacement.
Proposed Solution
Move the expiry branch ahead of the MAX_COOKIE_BYTES refusal, so a deletion is always honored regardless of how large a value it carries.
Found by @en0f while reviewing #86.
Problem
In
ChainCookies::store, theMAX_COOKIE_BYTESrefusal atsrc/cookies.rs:170runs before theexpiredbranch at:183. A cookie deletion costs no memory and no wire bytes, so the per-cookie size ceiling should not gate it. As written, an oversizedSet-CookiecarryingMax-Age=0is dropped, and the stale cookie stays in the store and keeps going out on later hops:The real trigger is frameworks that log out by re-sending the cookie's full value with
Max-Age=0rather than blanking it. A 4 KB JWT or SAML session cookie does exactly that.Same shape as the ordering mistake #88 fixed one branch below, where the incumbent was dropped before the budget check could refuse the replacement.
Proposed Solution
Move the expiry branch ahead of the
MAX_COOKIE_BYTESrefusal, so a deletion is always honored regardless of how large a value it carries.Found by @en0f while reviewing #86.