Skip to content

fix(cookie): parse request Cookie header as name/value pairs - #12871

Open
kali834x wants to merge 1 commit into
micronaut-projects:5.2.xfrom
kali834x:server-cookie-decoder-rfc6265
Open

fix(cookie): parse request Cookie header as name/value pairs#12871
kali834x wants to merge 1 commit into
micronaut-projects:5.2.xfrom
kali834x:server-cookie-decoder-rfc6265

Conversation

@kali834x

Copy link
Copy Markdown
Contributor

DefaultServerCookieDecoder.decode parses an inbound Cookie request header on runtimes without http-netty, but delegates to java.net.HttpCookie.parse, a Set-Cookie response parser. on a Cookie header with several pairs it returns only the first and drops the rest (SID=a; JSESSIONID=b yields just SID), throws IllegalArgumentException on a malformed name so a bad request turns into a 500, and treats Path/Domain/Max-Age as attributes on the inbound cookie, letting a client set cookie.getPath() which NettyCookies uses to filter which cookies reach the app. the NettyLaxServerCookieDecoder sibling backed by netty ServerCookieDecoder.LAX already parses it as a plain name/value list, so the two SPI implementations disagree on identical input. rewrite decode to split on ';', unwrap balanced quotes, and skip empty or unparsable pairs instead of interpreting attributes or throwing.

@HDPark95 HDPark95 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found one malformed-value case where the two server decoders still disagree:

String header = "a=\"unterminated; b=2";

At a915b6c, NettyLaxServerCookieDecoder returns only [b], while the new DefaultServerCookieDecoder returns [a, b] (with a's value still starting with the unmatched quote). Netty's decoder drops a value that starts with " but does not end with "; this implementation's unwrapValue instead returns that value unchanged.

That leaves the runtime-dependent behavior this change is trying to remove, and accepts an unparsable pair rather than skipping it. Could addCookie/unwrapValue signal and drop an unbalanced opening quote? I tested a minimal pre-unwrapping guard: the full :micronaut-http:test task passed 1,697 tests, and a cross-decoder spec covering this input passed both assertions.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes DefaultServerCookieDecoder to correctly parse an inbound HTTP Cookie request header as a sequence of name=value pairs (RFC 6265 §4.2.1), aligning behavior with the Netty-based decoder and avoiding treating Path/Domain as attributes or failing the whole header on malformed pairs.

Changes:

  • Replaced java.net.HttpCookie.parse usage with manual ;-delimited cookie-pair parsing and quoted-value unwrapping.
  • Changed behavior to skip empty/unparsable pairs instead of throwing on malformed input.
  • Updated/expanded tests to cover multiple cookies, malformed pairs, and quoted values.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
http/src/main/java/io/micronaut/http/cookie/DefaultServerCookieDecoder.java Reimplements Cookie header parsing to produce correct cookie-pairs and skip malformed segments safely.
http/src/test/java/io/micronaut/http/cookie/DefaultServerCookieDecoderTest.java Updates expectations and adds coverage for multi-cookie, malformed, and quoted-value parsing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +60 to +63
int equals = header.indexOf('=', start);
if (equals == -1 || equals >= end) {
return;
}
Comment on lines +69 to +73
try {
cookies.add(Cookie.of(name, value));
} catch (IllegalArgumentException e) {
// skip a single malformed pair rather than rejecting the whole header
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants