@@ -97,6 +97,18 @@ class HttpUtilsTest {
9797 .isEqualTo(" theme=dark; sessionId=[Filtered]; language=[Filtered]" )
9898 }
9999
100+ @Test
101+ fun `cookie filter preserves empty and padded base64 values` () {
102+ assertThat(
103+ HttpUtils .filterCookies(
104+ " empty=; data=YWJjZA==" ,
105+ KeyValueCollectionBehavior .denyList(),
106+ emptyList(),
107+ )
108+ )
109+ .isEqualTo(" empty=; data=YWJjZA==" )
110+ }
111+
100112 @Test
101113 fun `cookie filter uses only the first equals separator` () {
102114 assertThat(
@@ -109,6 +121,30 @@ class HttpUtilsTest {
109121 .isEqualTo(" theme=dark=contrast; token=[Filtered]" )
110122 }
111123
124+ @Test
125+ fun `cookie filter replaces malformed pairs without discarding valid pairs` () {
126+ assertThat(
127+ HttpUtils .filterCookies(
128+ " theme=dark; opaque; =secret; empty=; sessionId=secret" ,
129+ KeyValueCollectionBehavior .denyList(),
130+ emptyList(),
131+ )
132+ )
133+ .isEqualTo(" theme=dark;[Filtered];[Filtered]; empty=; sessionId=[Filtered]" )
134+ }
135+
136+ @Test
137+ fun `cookie allow list never exposes malformed pairs` () {
138+ assertThat(
139+ HttpUtils .filterCookies(
140+ " theme=dark; opaque; =secret" ,
141+ KeyValueCollectionBehavior .allowList(" theme" , " opaque" ),
142+ emptyList(),
143+ )
144+ )
145+ .isEqualTo(" theme=dark;[Filtered];[Filtered]" )
146+ }
147+
112148 @Test
113149 fun `set cookie filter preserves attributes` () {
114150 assertThat(
@@ -120,6 +156,26 @@ class HttpUtilsTest {
120156 .isEqualTo(" sessionId=[Filtered]; Path=/; HttpOnly; SameSite=Lax" )
121157 }
122158
159+ @Test
160+ fun `set cookie filter preserves empty and padded base64 values` () {
161+ assertThat(
162+ HttpUtils .filterSetCookie(
163+ " data=YWJjZA==; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Max-Age=3600; Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Lax" ,
164+ KeyValueCollectionBehavior .denyList(),
165+ )
166+ )
167+ .isEqualTo(
168+ " data=YWJjZA==; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Max-Age=3600; Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Lax"
169+ )
170+ assertThat(
171+ HttpUtils .filterSetCookie(
172+ " empty=; Path=/" ,
173+ KeyValueCollectionBehavior .denyList(),
174+ )
175+ )
176+ .isEqualTo(" empty=; Path=/" )
177+ }
178+
123179 @Test
124180 fun `set cookie allow list retains allowed non-sensitive value and attributes` () {
125181 assertThat(
@@ -131,6 +187,35 @@ class HttpUtilsTest {
131187 .isEqualTo(" theme=dark; Path=/; Secure" )
132188 }
133189
190+ @Test
191+ fun `set cookie filter replaces malformed cookie pair and discards attributes` () {
192+ assertThat(
193+ HttpUtils .filterSetCookie(
194+ " opaque; Path=/; HttpOnly" ,
195+ KeyValueCollectionBehavior .denyList(),
196+ )
197+ )
198+ .isEqualTo(" [Filtered]" )
199+ assertThat(
200+ HttpUtils .filterSetCookie(
201+ " =secret; Path=/; HttpOnly" ,
202+ KeyValueCollectionBehavior .denyList(),
203+ )
204+ )
205+ .isEqualTo(" [Filtered]" )
206+ }
207+
208+ @Test
209+ fun `set cookie allow list never exposes malformed cookie pair` () {
210+ assertThat(
211+ HttpUtils .filterSetCookie(
212+ " opaque; Path=/; HttpOnly" ,
213+ KeyValueCollectionBehavior .allowList(" opaque" ),
214+ )
215+ )
216+ .isEqualTo(" [Filtered]" )
217+ }
218+
134219 @Test
135220 fun `set cookie filter disables collection in off mode` () {
136221 assertThat(
0 commit comments