mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:30:42 +00:00
fix(qa-channel): reject non-http attachment urls
This commit is contained in:
@@ -8,6 +8,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- QA channel/security: reject non-HTTP(S) inbound attachment URLs before media fetch, and log rejected schemes so suspicious or misconfigured payloads are visible during debugging. (#70708) Thanks @vincentkoc.
|
||||
- Teams/security: require shared Bot Framework audience tokens to name the configured Teams app via verified `appid` or `azp`, blocking cross-bot token replay on the global audience. (#70724) Thanks @vincentkoc.
|
||||
- Plugins/startup: resolve bundled plugin Jiti loads relative to the target plugin module instead of the central loader, so Bun global installs no longer hang while discovering bundled image providers. (#70073) Thanks @yidianyiko.
|
||||
- Anthropic/CLI security: stop Claude CLI backend defaults from forcing `bypassPermissions`, and strip malformed permission-mode overrides instead of silently falling back to a bypass. (#70723) Thanks @vincentkoc.
|
||||
|
||||
12
extensions/qa-channel/src/inbound.test.ts
Normal file
12
extensions/qa-channel/src/inbound.test.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isHttpMediaUrl } from "./inbound.js";
|
||||
|
||||
describe("isHttpMediaUrl", () => {
|
||||
it("accepts only http and https urls", () => {
|
||||
expect(isHttpMediaUrl("https://example.com/image.png")).toBe(true);
|
||||
expect(isHttpMediaUrl("http://example.com/image.png")).toBe(true);
|
||||
expect(isHttpMediaUrl("file:///etc/passwd")).toBe(false);
|
||||
expect(isHttpMediaUrl("/etc/passwd")).toBe(false);
|
||||
expect(isHttpMediaUrl("data:text/plain;base64,SGVsbG8=")).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -9,6 +9,15 @@ import { buildQaTarget, sendQaBusMessage, type QaBusMessage } from "./bus-client
|
||||
import { getQaChannelRuntime } from "./runtime.js";
|
||||
import type { CoreConfig, ResolvedQaChannelAccount } from "./types.js";
|
||||
|
||||
export function isHttpMediaUrl(value: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(value);
|
||||
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveQaInboundMediaPayload(attachments: QaBusMessage["attachments"]) {
|
||||
if (!Array.isArray(attachments) || attachments.length === 0) {
|
||||
return {};
|
||||
@@ -33,6 +42,12 @@ async function resolveQaInboundMediaPayload(attachments: QaBusMessage["attachmen
|
||||
continue;
|
||||
}
|
||||
if (typeof attachment.url === "string" && attachment.url.trim()) {
|
||||
if (!isHttpMediaUrl(attachment.url)) {
|
||||
console.warn(
|
||||
`[qa-channel] inbound attachment URL rejected (non-http scheme): ${attachment.url}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const saved = await saveMediaSource(attachment.url, undefined, "inbound");
|
||||
mediaList.push({
|
||||
path: saved.path,
|
||||
|
||||
Reference in New Issue
Block a user