Don't validate cookie strings passed in the CookieMap constructor (#19945)

Co-authored-by: pfgithub <6010774+pfgithub@users.noreply.github.com>
This commit is contained in:
pfg
2025-05-27 20:14:21 -07:00
committed by GitHub
parent 5910504aeb
commit bf02d04479
2 changed files with 43 additions and 16 deletions

View File

@@ -60,14 +60,6 @@ ExceptionOr<Ref<CookieMap>> CookieMap::create(std::variant<Vector<Vector<String>
Vector<KeyValuePair<String, String>> cookies;
for (const auto& pair : pairs) {
if (pair.size() == 2) {
if (!pair[1].isEmpty() && !isValidHTTPHeaderValue(pair[1])) {
if (throwOnInvalidCookieString) {
return Exception { TypeError, "Invalid cookie string: cookie value is not valid"_s };
} else {
continue;
}
}
cookies.append(KeyValuePair<String, String>(pair[0], pair[1]));
} else if (throwOnInvalidCookieString) {
return Exception { TypeError, "Invalid cookie string: expected name=value pair"_s };
@@ -78,13 +70,6 @@ ExceptionOr<Ref<CookieMap>> CookieMap::create(std::variant<Vector<Vector<String>
[&](const HashMap<String, String>& pairs) -> ExceptionOr<Ref<CookieMap>> {
Vector<KeyValuePair<String, String>> cookies;
for (const auto& entry : pairs) {
if (!entry.value.isEmpty() && !isValidHTTPHeaderValue(entry.value)) {
if (throwOnInvalidCookieString) {
return Exception { TypeError, "Invalid cookie string: cookie value is not valid"_s };
} else {
continue;
}
}
cookies.append(KeyValuePair<String, String>(entry.key, entry.value));
}

View File

@@ -323,7 +323,7 @@ describe("cookie path option", () => {
"/x/y": {
GET(r) {
r.cookies.set("user", "a", { maxAge: 3600, path: "/" });
const cookie = r.cookies.toSetCookieHeaders().at(0);
const cookie = r.cookies.toSetCookieHeaders().at(0)!;
return new Response("ok", {
headers: { "set-cookie": cookie },
});
@@ -371,3 +371,45 @@ test("delete cookie invalid path option", () => {
`"Invalid cookie name: contains invalid characters"`,
);
});
describe("Bun.CookieMap constructor", () => {
test("throws for invalid array", () => {
expect(() => new Bun.CookieMap([["abc defg =fhaingj809读写汉字学中文"]])).toThrowErrorMatchingInlineSnapshot(
`"Expected arrays of exactly two strings"`,
);
});
test("accepts unicode cookie value in object", () => {
const map = new Bun.CookieMap({
"cookie key": "读写汉字学中文",
});
expect(map.get("cookie key")).toBe("读写汉字学中文");
});
test("accepts unicode cookie value in array", () => {
const map = new Bun.CookieMap([["cookie key", "读写汉字学中文"]]);
expect(map.get("cookie key")).toBe("读写汉字学中文");
});
test("accepts unicode cookie value in string", () => {
const map = new Bun.CookieMap("cookie key=读写汉字学中文");
expect(map.get("cookie key")).toBe("读写汉字学中文");
});
test("serializes unicode cookie value", () => {
const map = new Bun.CookieMap();
map.set("cookiekey", "读写汉字学中文");
expect(map.toSetCookieHeaders()).toMatchInlineSnapshot(`
[
"cookiekey=%E8%AF%BB%E5%86%99%E6%B1%89%E5%AD%97%E5%AD%A6%E4%B8%AD%E6%96%87; Path=/; SameSite=Lax",
]
`);
// re-parse
const reparsed = new Bun.CookieMap(map.toSetCookieHeaders()[0].split(";")[0]!);
expect(reparsed.get("cookiekey")).toBe("读写汉字学中文");
});
test("doesn't parse percent encoded value in object or array", () => {
const map = new Bun.CookieMap({
"cookiekey": "%E8%AF%BB%E5%86%99%E6%B1%89%E5%AD%97%E5%AD%A6%E4%B8%AD%E6%96%87",
});
const map2 = new Bun.CookieMap([["cookiekey", "%E8%AF%BB%E5%86%99%E6%B1%89%E5%AD%97%E5%AD%A6%E4%B8%AD%E6%96%87"]]);
expect(map.get("cookiekey")).toBe("%E8%AF%BB%E5%86%99%E6%B1%89%E5%AD%97%E5%AD%A6%E4%B8%AD%E6%96%87");
expect(map2.get("cookiekey")).toBe("%E8%AF%BB%E5%86%99%E6%B1%89%E5%AD%97%E5%AD%A6%E4%B8%AD%E6%96%87");
});
});