mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 16:44:45 +00:00
fix(media): reject malformed redirect locations
This commit is contained in:
@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
|
||||
- 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.
|
||||
- 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.
|
||||
- Voice-call webhooks: parse webhook and realtime upgrade paths without trusting malformed Host headers, avoiding 500s before provider signature checks or path rejection.
|
||||
- Media store: reject malformed redirect `Location` headers as media-download failures instead of letting URL parsing escape the async response callback.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
@@ -217,4 +217,13 @@ describe("media store redirects", () => {
|
||||
});
|
||||
await expectRedirectSaveFailure("Redirect loop or missing Location header");
|
||||
});
|
||||
|
||||
it("fails when redirect location is malformed", async () => {
|
||||
mockRequest.mockImplementationOnce((_url, _opts, cb) => {
|
||||
const exchange = mockRedirectExchange({ location: "http://[" });
|
||||
exchange.send(cb);
|
||||
return exchange.req;
|
||||
});
|
||||
await expectRedirectSaveFailure("Invalid redirect Location header");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -230,12 +230,20 @@ async function downloadToFile(
|
||||
reject(new Error(`Redirect loop or missing Location header`));
|
||||
return;
|
||||
}
|
||||
const redirectUrl = new URL(location, url).href;
|
||||
let redirectUrl: URL;
|
||||
try {
|
||||
redirectUrl = new URL(location, url);
|
||||
} catch {
|
||||
reject(new Error("Invalid redirect Location header"));
|
||||
return;
|
||||
}
|
||||
const redirectHeaders =
|
||||
new URL(redirectUrl).origin === parsedUrl.origin
|
||||
redirectUrl.origin === parsedUrl.origin
|
||||
? headers
|
||||
: retainSafeHeadersForCrossOriginRedirect(headers);
|
||||
resolve(downloadToFile(redirectUrl, dest, redirectHeaders, maxRedirects - 1, maxBytes));
|
||||
resolve(
|
||||
downloadToFile(redirectUrl.href, dest, redirectHeaders, maxRedirects - 1, maxBytes),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!res.statusCode || res.statusCode >= 400) {
|
||||
|
||||
Reference in New Issue
Block a user