Skip to content

AWS Lambda adapter doubles request cookies when the event carries both headers.cookie and cookies[] #283

Description

@DL-datalobby

Environment

srvx 0.11.16 through 0.12.4 (latest — dist/adapters/aws-lambda.mjs is identical on this path), Node 22 / Bun, AWS Lambda Function URL behind CloudFront.

Bug

awsEventHeaders copies every event.headers entry and then appends every event.cookies[] entry:

function awsEventHeaders(event) {
	const headers = new Headers();
	for (const [key, value] of Object.entries(event.headers)) if (value) headers.set(key, value);
	if ("cookies" in event && event.cookies) for (const cookie of event.cookies) headers.append("cookie", cookie);
	return headers;
}

Lambda Function URL events (payload 2.0) can carry cookies in both places — the raw cookie string in event.headers and the parsed event.cookies[] array. When they do, every cookie ends up in the Headers object twice, and since Headers.get("cookie") joins multiple cookie values with "; " (the HTTP/2 cookie rule, in both Node and Bun), the fetch handler sees every cookie doubled:

cookie: session=abc; theme=dark; session=abc; theme=dark

requestToAwsEvent (used by invokeLambdaHandler) has the same shape — it pushes each cookie value into cookies[] and keeps it in headers — so the test helper reproduces the doubling locally:

import { toLambdaHandler, invokeLambdaHandler } from "srvx/aws-lambda";

const handler = toLambdaHandler({
  fetch: (request) => new Response(request.headers.get("cookie")),
});
const res = await invokeLambdaHandler(
  handler,
  new Request("https://example.com/", { headers: { cookie: "session=abc" } }),
);
console.log(await res.text()); // "session=abc; session=abc"  — expected "session=abc"

Impact

Any downstream consumer of request.headers.get("cookie") or a cookie parser that is sensitive to duplicate names misbehaves. In our production app (CloudFront + Function URL) a duplicate-cookie repair path fired on every request because a single-cookie jar arrived looking duplicated.

Suggested fix

When event.cookies is present, treat it as authoritative and skip the cookie key while copying event.headers (mirrors the documented API Gateway payload-2.0 semantics, where cookies[] replaces the header). Same skip in requestToAwsEvent when building headers.

We currently work around it by deleting the cookie key from event.headers in a wrapper before handing the event to toLambdaHandler. Happy to open a PR if the suggested direction sounds right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions