mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-15 19:06:05 +00:00
* refactor(browser): collapse Playwright export paths * refactor(browser): remove dead plugin exports * refactor(codex): remove dead app-server exports * refactor(codex): remove remaining dead exports * test(codex): use canonical private-type owners * test(browser): isolate proxy startup state * test(browser): remove stale chrome imports * refactor(codex): privatize remaining helpers * chore(deadcode): refresh export baseline after rebase * refactor(browser): finish canonical helper ownership * refactor: fix dead-export cleanup gates * refactor(codex): keep runtime facades LOC-neutral * chore(ci): refresh TypeScript LOC baseline * chore(deadcode): refresh ratchets after rebase * chore(ci): refresh LOC baseline after main advance * chore(deadcode): align ratchets with latest main
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
/**
|
|
* Browser-local SDK security bridge plus directory creation helper.
|
|
*/
|
|
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import {
|
|
findExistingAncestor,
|
|
pathScope as sdkPathScope,
|
|
} from "openclaw/plugin-sdk/security-runtime";
|
|
|
|
export {
|
|
ensurePortAvailable,
|
|
extractErrorCode,
|
|
formatErrorMessage,
|
|
hasProxyEnvConfigured,
|
|
isPrivateNetworkAllowedByPolicy,
|
|
matchesHostnameAllowlist,
|
|
normalizeHostname,
|
|
resolveExistingPathsWithinRoot,
|
|
resolvePinnedHostnameWithPolicy,
|
|
sanitizeUntrustedFileName,
|
|
resolveStrictExistingPathsWithinRoot,
|
|
SsrFBlockedError,
|
|
writeExternalFileWithinRoot,
|
|
wrapExternalContent,
|
|
} from "openclaw/plugin-sdk/security-runtime";
|
|
export type { LookupFn, SsrFPolicy } from "openclaw/plugin-sdk/security-runtime";
|
|
export { sdkPathScope as pathScope };
|
|
|
|
/** Ensures an absolute directory exists without escaping its nearest existing ancestor. */
|
|
export async function ensureAbsoluteDirectory(
|
|
dirPath: string,
|
|
options?: { scopeLabel?: string; mode?: number },
|
|
): Promise<{ ok: true; path: string } | { ok: false; error: Error }> {
|
|
const absolutePath = path.resolve(dirPath);
|
|
const scopeLabel = options?.scopeLabel ?? "directory";
|
|
const existingAncestor = await findExistingAncestor(absolutePath);
|
|
if (!existingAncestor) {
|
|
return { ok: false, error: new Error(`Invalid path: must stay within ${scopeLabel}`) };
|
|
}
|
|
if (existingAncestor === absolutePath) {
|
|
try {
|
|
const stat = await fs.lstat(absolutePath);
|
|
if (!stat.isSymbolicLink() && stat.isDirectory()) {
|
|
return { ok: true, path: absolutePath };
|
|
}
|
|
} catch {
|
|
// Fall through to the uniform invalid-path result below.
|
|
}
|
|
return { ok: false, error: new Error(`Invalid path: must stay within ${scopeLabel}`) };
|
|
}
|
|
const result = await sdkPathScope(existingAncestor, {
|
|
label: options?.scopeLabel ?? "directory",
|
|
}).ensureDir(path.relative(existingAncestor, absolutePath), { mode: options?.mode });
|
|
if (result.ok) {
|
|
return result;
|
|
}
|
|
return { ok: false, error: new Error(result.error) };
|
|
}
|