Skip to content

Commit

Permalink
Add specs for invalid special characters in Cookie (#15244)
Browse files Browse the repository at this point in the history
These specs describe the status quo of special character handling in HTTP::Cookie per #15218.

---------

Co-authored-by: Julien Portalier <[email protected]>
  • Loading branch information
straight-shoota and ysbaddaden authored Dec 7, 2024
1 parent 655b8a5 commit 972e184
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions spec/std/http/cookie_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ private def parse_set_cookie(header)
cookie.not_nil!
end

# invalid printable ascii characters, non-printable ascii characters and control characters
private INVALID_COOKIE_VALUES = ("\x00".."\x08").to_a + ("\x0A".."\x1F").to_a + ["\r", "\t", "\n", %(" "), %("), ",", ";", "\\", "\x7f", "\xFF", "🍪"]

module HTTP
describe Cookie do
it "#==" do
Expand Down Expand Up @@ -45,6 +48,12 @@ module HTTP
expect_raises IO::Error, "Invalid cookie value" do
HTTP::Cookie.new("x", %(foo\rbar))
end

INVALID_COOKIE_VALUES.each do |char|
expect_raises IO::Error, "Invalid cookie value" do
HTTP::Cookie.new("x", char)
end
end
end

describe "with a security prefix" do
Expand Down Expand Up @@ -132,14 +141,10 @@ module HTTP
describe "#value=" do
it "raises on invalid value" do
cookie = HTTP::Cookie.new("x", "")
invalid_values = {
'"', ',', ';', '\\', # invalid printable ascii characters
'\r', '\t', '\n', # non-printable ascii characters
}.map { |c| "foo#{c}bar" }

invalid_values.each do |invalid_value|
INVALID_COOKIE_VALUES.each do |v|
expect_raises IO::Error, "Invalid cookie value" do
cookie.value = invalid_value
cookie.value = "foo#{v}bar"
end
end
end
Expand Down Expand Up @@ -562,6 +567,16 @@ module HTTP
cookies = Cookies.from_client_headers Headers{"Cookie" => "a=b", "Set-Cookie" => "x=y"}
cookies.to_h.should eq({"a" => Cookie.new("a", "b")})
end

it "chops value at the first invalid byte" do
HTTP::Cookies.from_client_headers(
HTTP::Headers{"Cookie" => "ginger=snap; cookie=hm🍪delicious; snicker=doodle"}
).to_h.should eq({
"ginger" => HTTP::Cookie.new("ginger", "snap"),
"cookie" => HTTP::Cookie.new("cookie", "hm"),
"snicker" => HTTP::Cookie.new("snicker", "doodle"),
})
end
end

describe ".from_server_headers" do
Expand All @@ -573,6 +588,15 @@ module HTTP
cookies = Cookies.from_server_headers Headers{"Set-Cookie" => "a=b", "Cookie" => "x=y"}
cookies.to_h.should eq({"a" => Cookie.new("a", "b")})
end

it "drops cookies with invalid byte in value" do
HTTP::Cookies.from_server_headers(
HTTP::Headers{"Set-Cookie" => ["ginger=snap", "cookie=hm🍪delicious", "snicker=doodle"]}
).to_h.should eq({
"ginger" => HTTP::Cookie.new("ginger", "snap"),
"snicker" => HTTP::Cookie.new("snicker", "doodle"),
})
end
end

it "allows adding cookies and retrieving" do
Expand Down

0 comments on commit 972e184

Please sign in to comment.