fix(slack): ignore malformed media redirects

This commit is contained in:
Vincent Koc
2026-05-14 15:08:16 +08:00
parent b8dccbf310
commit d41907a5cb
3 changed files with 21 additions and 1 deletions

View File

@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
- 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.
- CLI/migrate: drop trailing periods from Codex migrate item messages and `REASON_CODE_MESSAGES` strings so plan/result rows read as labels instead of sentence fragments. (#81705) Thanks @sjf.
- Slack: treat malformed private-file redirect `Location` headers as unfollowable redirects instead of failing Slack media downloads.
- Matrix: ignore malformed percent-encoding in optional location URI parameters instead of letting a bad `geo:` event abort inbound message handling.
- Plugins: discover provider plugins from `setup.providers[].envVars` credentials during provider discovery while keeping the deprecated `providerAuthEnvVars` fallback. (#81542) Thanks @JARVIS-Glasses.
- Docs/Codex harness: clarify that per-agent `CODEX_HOME` isolates `~/.codex` while inherited `HOME` intentionally keeps `.agents` discovery and subprocess user-home state available.

View File

@@ -359,6 +359,20 @@ describe("fetchWithSlackAuth", () => {
expect(mockFetch).toHaveBeenCalledTimes(1);
});
it("returns redirect response when location header is malformed", async () => {
const redirectResponse = new Response(null, {
status: 302,
headers: { location: "http://[::1" },
});
mockFetch.mockResolvedValueOnce(redirectResponse);
const result = await fetchWithSlackAuth("https://files.slack.com/test.jpg", "xoxb-test-token");
expect(result).toBe(redirectResponse);
expect(mockFetch).toHaveBeenCalledTimes(1);
});
it("returns 4xx/5xx responses directly without following", async () => {
const errorResponse = new Response("Not Found", {
status: 404,

View File

@@ -122,7 +122,12 @@ export async function fetchWithSlackAuth(url: string, token: string): Promise<Re
return initialRes;
}
const resolvedUrl = new URL(redirectUrl, parsed.href);
let resolvedUrl: URL;
try {
resolvedUrl = new URL(redirectUrl, parsed.href);
} catch {
return initialRes;
}
if (resolvedUrl.protocol !== "https:") {
return initialRes;
}