mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 15:14:45 +00:00
fix(qa-channel): reject malformed inline attachment data
This commit is contained in:
@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Google Meet/Codex: report malformed node proxy `payloadJSON` responses with plugin-owned errors instead of leaking raw JSON parser failures.
|
||||
- Debug proxy: reject malformed relative-form proxy targets with a controlled 400 response instead of letting URL parsing escape the request handler.
|
||||
- File transfer: reject malformed inline `file_write` base64 before computing hashes or invoking paired nodes, avoiding Node's lenient base64 decoder.
|
||||
- QA channel: skip malformed inline inbound attachment base64 instead of staging silently corrupted media for agent turns.
|
||||
- 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.
|
||||
|
||||
@@ -124,6 +124,31 @@ describe("handleQaInbound", () => {
|
||||
expect(ctxPayload?.SenderId).toBe("alice");
|
||||
});
|
||||
|
||||
it("skips malformed inline attachment base64 without dropping the message", async () => {
|
||||
const runtime = createPluginRuntimeMock();
|
||||
setQaChannelRuntime(runtime);
|
||||
|
||||
await handleQaInbound(
|
||||
createQaInboundParams({
|
||||
message: {
|
||||
attachments: [
|
||||
{
|
||||
id: "attachment-1",
|
||||
kind: "image",
|
||||
mimeType: "image/png",
|
||||
contentBase64: "AAA@@@",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(runtime.channel.turn.runAssembled).toHaveBeenCalledTimes(1);
|
||||
const ctxPayload = firstRunAssembledParams(runtime).ctxPayload;
|
||||
expect(ctxPayload.MediaPath).toBeUndefined();
|
||||
expect(ctxPayload.MediaPaths).toBeUndefined();
|
||||
});
|
||||
|
||||
it("uses allowFrom as the group sender fallback for allowlist policy", async () => {
|
||||
const runtime = createPluginRuntimeMock();
|
||||
setQaChannelRuntime(runtime);
|
||||
|
||||
@@ -19,6 +19,18 @@ export function isHttpMediaUrl(value: string): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeBase64ForCompare(value: string): string {
|
||||
return value.replace(/=+$/u, "").replace(/-/gu, "+").replace(/_/gu, "/");
|
||||
}
|
||||
|
||||
function decodeAttachmentBase64(value: string): Buffer | null {
|
||||
const buffer = Buffer.from(value, "base64");
|
||||
if (normalizeBase64ForCompare(buffer.toString("base64")) !== normalizeBase64ForCompare(value)) {
|
||||
return null;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
async function resolveQaInboundMediaPayload(attachments: QaBusMessage["attachments"]) {
|
||||
if (!Array.isArray(attachments) || attachments.length === 0) {
|
||||
return {};
|
||||
@@ -29,8 +41,13 @@ async function resolveQaInboundMediaPayload(attachments: QaBusMessage["attachmen
|
||||
continue;
|
||||
}
|
||||
if (typeof attachment.contentBase64 === "string" && attachment.contentBase64.trim()) {
|
||||
const buffer = decodeAttachmentBase64(attachment.contentBase64);
|
||||
if (!buffer) {
|
||||
console.warn("[qa-channel] inbound attachment contentBase64 rejected (invalid base64)");
|
||||
continue;
|
||||
}
|
||||
const saved = await saveMediaBuffer(
|
||||
Buffer.from(attachment.contentBase64, "base64"),
|
||||
buffer,
|
||||
attachment.mimeType,
|
||||
"inbound",
|
||||
undefined,
|
||||
|
||||
Reference in New Issue
Block a user