mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 05:11:25 +00:00
fix: guard remote media fetches with SSRF checks
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import type { SsrFPolicy } from "../infra/net/ssrf.js";
|
||||
import { logVerbose, shouldLogVerbose } from "../globals.js";
|
||||
import { type MediaKind, maxBytesForKind, mediaKindFromMime } from "../media/constants.js";
|
||||
import { fetchRemoteMedia } from "../media/fetch.js";
|
||||
@@ -23,6 +24,7 @@ export type WebMediaResult = {
|
||||
type WebMediaOptions = {
|
||||
maxBytes?: number;
|
||||
optimizeImages?: boolean;
|
||||
ssrfPolicy?: SsrFPolicy;
|
||||
};
|
||||
|
||||
const HEIC_MIME_RE = /^image\/hei[cf]$/i;
|
||||
@@ -122,7 +124,7 @@ async function loadWebMediaInternal(
|
||||
mediaUrl: string,
|
||||
options: WebMediaOptions = {},
|
||||
): Promise<WebMediaResult> {
|
||||
const { maxBytes, optimizeImages = true } = options;
|
||||
const { maxBytes, optimizeImages = true, ssrfPolicy } = options;
|
||||
// Use fileURLToPath for proper handling of file:// URLs (handles file://localhost/path, etc.)
|
||||
if (mediaUrl.startsWith("file://")) {
|
||||
try {
|
||||
@@ -209,7 +211,7 @@ async function loadWebMediaInternal(
|
||||
: optimizeImages
|
||||
? Math.max(maxBytes, defaultFetchCap)
|
||||
: maxBytes;
|
||||
const fetched = await fetchRemoteMedia({ url: mediaUrl, maxBytes: fetchCap });
|
||||
const fetched = await fetchRemoteMedia({ url: mediaUrl, maxBytes: fetchCap, ssrfPolicy });
|
||||
const { buffer, contentType, fileName } = fetched;
|
||||
const kind = mediaKindFromMime(contentType);
|
||||
return await clampAndFinalize({ buffer, contentType, kind, fileName });
|
||||
@@ -239,20 +241,27 @@ async function loadWebMediaInternal(
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadWebMedia(mediaUrl: string, maxBytes?: number): Promise<WebMediaResult> {
|
||||
export async function loadWebMedia(
|
||||
mediaUrl: string,
|
||||
maxBytes?: number,
|
||||
options?: { ssrfPolicy?: SsrFPolicy },
|
||||
): Promise<WebMediaResult> {
|
||||
return await loadWebMediaInternal(mediaUrl, {
|
||||
maxBytes,
|
||||
optimizeImages: true,
|
||||
ssrfPolicy: options?.ssrfPolicy,
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadWebMediaRaw(
|
||||
mediaUrl: string,
|
||||
maxBytes?: number,
|
||||
options?: { ssrfPolicy?: SsrFPolicy },
|
||||
): Promise<WebMediaResult> {
|
||||
return await loadWebMediaInternal(mediaUrl, {
|
||||
maxBytes,
|
||||
optimizeImages: false,
|
||||
ssrfPolicy: options?.ssrfPolicy,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user