fix: reject a non-string protocolVersion, and drop the test double casts
Copilot review follow-ups: - `applyProtocolVersion` took the value straight from an unvalidated JSON body and went to `RegExp.test`, which coerces — `123` and `true` both matched the token pattern and reached `Transport.setProtocolVersion` with the wrong type. It now takes `unknown` and checks `typeof === "string"` first, with cases for the coercible values. - Replace `as unknown as Transport` in the new session fixtures with a `makeTransport()` helper returning a structurally valid `Transport`, so an interface change stays visible to the tests. - Drop `as unknown as typeof fetch` in the new transport test — `vi.fn<typeof fetch>()` is already the right type. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119LaPQ3v4NyBK3ZTdM9j84
This commit is contained in:
parent
7a74b5eba1
commit
ddfce0f7ac
2 changed files with 26 additions and 11 deletions
|
|
@ -542,10 +542,7 @@ describe("RemoteClientTransport", () => {
|
|||
return new Response("not found", { status: 404 });
|
||||
});
|
||||
|
||||
const transport = new RemoteClientTransport(
|
||||
{ baseUrl, fetchFn: fetchFn as unknown as typeof fetch },
|
||||
config,
|
||||
);
|
||||
const transport = new RemoteClientTransport({ baseUrl, fetchFn }, config);
|
||||
await transport.start();
|
||||
|
||||
// Pre-initialize sends carry no version (none negotiated yet).
|
||||
|
|
|
|||
|
|
@ -25,6 +25,16 @@ function makeFetchEntry(
|
|||
};
|
||||
}
|
||||
|
||||
/** A structurally valid `Transport`, so a fixture needs no cast. */
|
||||
function makeTransport(overrides: Partial<Transport> = {}): Transport {
|
||||
return {
|
||||
start: async () => {},
|
||||
send: async () => {},
|
||||
close: async () => {},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("RemoteSession", () => {
|
||||
it("queues events before a consumer attaches and drains them on attach", () => {
|
||||
const session = new RemoteSession("s1");
|
||||
|
|
@ -125,7 +135,7 @@ describe("RemoteSession", () => {
|
|||
it("applyProtocolVersion forwards a new version to the transport once", () => {
|
||||
const session = new RemoteSession("s8a");
|
||||
const setProtocolVersion = vi.fn();
|
||||
session.setTransport({ setProtocolVersion } as unknown as Transport);
|
||||
session.setTransport(makeTransport({ setProtocolVersion }));
|
||||
|
||||
session.applyProtocolVersion("2025-11-25");
|
||||
session.applyProtocolVersion("2025-11-25");
|
||||
|
|
@ -136,21 +146,26 @@ describe("RemoteSession", () => {
|
|||
expect(setProtocolVersion).toHaveBeenLastCalledWith("2026-07-28");
|
||||
});
|
||||
|
||||
it("applyProtocolVersion ignores an absent or non-token version", () => {
|
||||
it("applyProtocolVersion ignores an absent, non-token, or non-string version", () => {
|
||||
const session = new RemoteSession("s8b");
|
||||
const setProtocolVersion = vi.fn();
|
||||
session.setTransport({ setProtocolVersion } as unknown as Transport);
|
||||
session.setTransport(makeTransport({ setProtocolVersion }));
|
||||
|
||||
session.applyProtocolVersion(undefined);
|
||||
// Header injection attempt — must never reach the upstream transport.
|
||||
session.applyProtocolVersion("2025-11-25\r\nX-Evil: 1");
|
||||
session.applyProtocolVersion("");
|
||||
// The value arrives from an unvalidated JSON body, so a non-string must be
|
||||
// rejected on its type — `RegExp.test` would coerce these into a match.
|
||||
session.applyProtocolVersion(123);
|
||||
session.applyProtocolVersion(true);
|
||||
session.applyProtocolVersion(null);
|
||||
expect(setProtocolVersion).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("applyProtocolVersion is a no-op on a transport without setProtocolVersion (stdio)", () => {
|
||||
const session = new RemoteSession("s8c");
|
||||
session.setTransport({} as unknown as Transport);
|
||||
session.setTransport(makeTransport());
|
||||
expect(() => session.applyProtocolVersion("2025-11-25")).not.toThrow();
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue