mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 20:38:27 +00:00
Security/Browser: constrain trace and download output paths to OpenClaw temp roots (#15652)
* Browser/Security: constrain trace and download output paths to temp roots * Changelog: remove advisory ID from pre-public security note * Browser/Security: constrain trace and download output paths to temp roots * Changelog: remove advisory ID from pre-public security note * test(bluebubbles): align timeout status expectation to 408 * test(discord): remove unused race-condition counter in threading test * test(bluebubbles): align timeout status expectation to 408
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
resolveProfileContext,
|
||||
SELECTOR_UNSUPPORTED_MESSAGE,
|
||||
} from "./agent.shared.js";
|
||||
import { DEFAULT_DOWNLOAD_DIR, resolvePathWithinRoot } from "./path-output.js";
|
||||
import { jsonError, toBoolean, toNumber, toStringArray, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserAgentActRoutes(
|
||||
@@ -430,7 +431,7 @@ export function registerBrowserAgentActRoutes(
|
||||
}
|
||||
const body = readBody(req);
|
||||
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
||||
const out = toStringOrEmpty(body.path) || undefined;
|
||||
const out = toStringOrEmpty(body.path) || "";
|
||||
const timeoutMs = toNumber(body.timeoutMs);
|
||||
try {
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId);
|
||||
@@ -438,10 +439,23 @@ export function registerBrowserAgentActRoutes(
|
||||
if (!pw) {
|
||||
return;
|
||||
}
|
||||
let downloadPath: string | undefined;
|
||||
if (out.trim()) {
|
||||
const downloadPathResult = resolvePathWithinRoot({
|
||||
rootDir: DEFAULT_DOWNLOAD_DIR,
|
||||
requestedPath: out,
|
||||
scopeLabel: "downloads directory",
|
||||
});
|
||||
if (!downloadPathResult.ok) {
|
||||
res.status(400).json({ error: downloadPathResult.error });
|
||||
return;
|
||||
}
|
||||
downloadPath = downloadPathResult.path;
|
||||
}
|
||||
const result = await pw.waitForDownloadViaPlaywright({
|
||||
cdpUrl: profileCtx.profile.cdpUrl,
|
||||
targetId: tab.targetId,
|
||||
path: out,
|
||||
path: downloadPath,
|
||||
timeoutMs: timeoutMs ?? undefined,
|
||||
});
|
||||
res.json({ ok: true, targetId: tab.targetId, download: result });
|
||||
@@ -467,6 +481,15 @@ export function registerBrowserAgentActRoutes(
|
||||
return jsonError(res, 400, "path is required");
|
||||
}
|
||||
try {
|
||||
const downloadPathResult = resolvePathWithinRoot({
|
||||
rootDir: DEFAULT_DOWNLOAD_DIR,
|
||||
requestedPath: out,
|
||||
scopeLabel: "downloads directory",
|
||||
});
|
||||
if (!downloadPathResult.ok) {
|
||||
res.status(400).json({ error: downloadPathResult.error });
|
||||
return;
|
||||
}
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId);
|
||||
const pw = await requirePwAi(res, "download");
|
||||
if (!pw) {
|
||||
@@ -476,7 +499,7 @@ export function registerBrowserAgentActRoutes(
|
||||
cdpUrl: profileCtx.profile.cdpUrl,
|
||||
targetId: tab.targetId,
|
||||
ref,
|
||||
path: out,
|
||||
path: downloadPathResult.path,
|
||||
timeoutMs: timeoutMs ?? undefined,
|
||||
});
|
||||
res.json({ ok: true, targetId: tab.targetId, download: result });
|
||||
|
||||
Reference in New Issue
Block a user