Files
openclaw/extensions/browser/src/plugin-service.ts
Agustin Rivera dafcaf9d69 fix(browser): harden browser control override loading (#62663)
* fix(browser): harden browser control overrides

* fix(lint): prepare boundary artifacts for extension oxlint

* docs(changelog): add browser override hardening entry

* fix(lint): avoid duplicate boundary prep

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
Co-authored-by: Devin Robison <drobison00@users.noreply.github.com>
2026-04-08 13:24:47 -06:00

50 lines
1.6 KiB
TypeScript

import {
startLazyPluginServiceModule,
type LazyPluginServiceHandle,
type OpenClawPluginService,
} from "openclaw/plugin-sdk/browser-node-runtime";
type BrowserControlHandle = LazyPluginServiceHandle | null;
const UNSAFE_BROWSER_CONTROL_OVERRIDE_SPECIFIER = /^(?:data|http|https|node):/i;
function validateBrowserControlOverrideSpecifier(specifier: string): string {
const trimmed = specifier.trim();
if (UNSAFE_BROWSER_CONTROL_OVERRIDE_SPECIFIER.test(trimmed)) {
throw new Error(`Refusing unsafe browser control override specifier: ${trimmed}`);
}
return trimmed;
}
export function createBrowserPluginService(): OpenClawPluginService {
let handle: BrowserControlHandle = null;
return {
id: "browser-control",
start: async () => {
if (handle) {
return;
}
handle = await startLazyPluginServiceModule({
skipEnvVar: "OPENCLAW_SKIP_BROWSER_CONTROL_SERVER",
overrideEnvVar: "OPENCLAW_BROWSER_CONTROL_MODULE",
validateOverrideSpecifier: validateBrowserControlOverrideSpecifier,
// Keep the default module import static so compiled builds still bundle it.
loadDefaultModule: async () => await import("./server.js"),
startExportNames: [
"startBrowserControlServiceFromConfig",
"startBrowserControlServerFromConfig",
],
stopExportNames: ["stopBrowserControlService", "stopBrowserControlServer"],
});
},
stop: async () => {
const current = handle;
handle = null;
if (!current) {
return;
}
await current.stop().catch(() => {});
},
};
}