Skip to content

Commit 462a056

Browse files
committed
fix(gateway): ignore malformed host on json routes
1 parent fe25ed2 commit 462a056

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Docs: https://docs.openclaw.ai
1717
- CLI: lazy-load model, plugin, and device runtime helpers for command actions so parent/help output renders without importing those runtime paths.
1818
- Gateway/session history: carry monotonic transcript message sequence through live updates and refresh SSE history when stale sequence input would otherwise append bad incremental state. (#81474) Thanks @samzong.
1919
- Security/sandbox: include Windows `USERPROFILE` in the sandbox blocked home roots so credential-bearing binds (such as `.codex`, `.openclaw`, or `.ssh` under the Windows user profile) are denied even when `HOME` points at a different shell home. (#63074) Thanks @luoyanglang.
20+
- Gateway/OpenAI-compatible HTTP: parse shared JSON endpoint paths without trusting malformed Host headers, avoiding 500s before `/v1/chat/completions`, `/v1/responses`, and `/v1/embeddings` request handling.
2021
- Models config/auth: stop inferring provider env-var markers from broad `^[A-Z_][A-Z0-9_]*$` strings, and resolve config-backed provider `apiKey` values only through structured env SecretRefs (`secrets.providers[id]` / `secrets.defaults`), so unrelated env vars cannot accidentally become provider credentials. Thanks @sallyom.
2122
- Media fetch: skip allocating and buffering the response body for bodyless media responses (HEAD probes and 204-style empty bodies), avoiding wasted heap on streams that carry no payload. Thanks @shakkernerd.
2223
- CLI/onboarding: forward provider-specific auth flags (e.g. `--openai-api-key`) through the onboarding wizard so they reach provider auth methods via `ctx.opts`, letting `--openai-api-key "$OPENAI_API_KEY"` skip the redundant "use existing env var?" prompt in non-interactive harnesses. (#81669) Thanks @sjf.

src/gateway/http-endpoint-helpers.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,28 @@ describe("handleGatewayPostJsonEndpoint", () => {
9595
});
9696
});
9797

98+
it("matches paths without trusting malformed Host headers", async () => {
99+
vi.mocked(authorizeGatewayHttpRequestOrReply).mockResolvedValue({
100+
trustDeclaredOperatorScopes: true,
101+
});
102+
vi.mocked(readJsonBodyOrError).mockResolvedValue({ ok: true });
103+
104+
const result = await handleGatewayPostJsonEndpoint(
105+
{
106+
url: "/v1/ok",
107+
method: "POST",
108+
headers: { host: "[" },
109+
} as unknown as IncomingMessage,
110+
{} as unknown as ServerResponse,
111+
{ pathname: "/v1/ok", auth: {} as unknown as ResolvedGatewayAuth, maxBodyBytes: 123 },
112+
);
113+
114+
expect(result).toEqual({
115+
body: { ok: true },
116+
requestAuth: { trustDeclaredOperatorScopes: true },
117+
});
118+
});
119+
98120
it("returns undefined and replies when required operator scope is missing", async () => {
99121
vi.mocked(authorizeGatewayHttpRequestOrReply).mockResolvedValue({
100122
trustDeclaredOperatorScopes: false,

src/gateway/http-endpoint-helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export async function handleGatewayPostJsonEndpoint(
3030
) => string[];
3131
},
3232
): Promise<false | { body: unknown; requestAuth: AuthorizedGatewayHttpRequest } | undefined> {
33-
const url = new URL(req.url ?? "/", `http://${req.headers.host || "localhost"}`);
33+
const url = new URL(req.url ?? "/", "http://localhost");
3434
if (url.pathname !== opts.pathname) {
3535
return false;
3636
}

0 commit comments

Comments
 (0)