/* eslint-disable @typescript-eslint/no-explicit-any */ /** * Worker lockdown — MUST be the first import of the worker entry so its * side effects run before the script engine (or anything else) is evaluated. * * User scripts may only compute over the bar data we pass in; every network * and storage capability inside the worker is replaced with a throwing stub. * This is defensive sandboxing for user-authored code (same model as any * plugin system) — combined with the main-thread watchdog that terminates * the worker on timeouts. */ const DENIED = "دسترسی شبکه/ذخیره‌سازی در اسکریپت شخصی مجاز نیست"; function deny(): never { throw new Error(DENIED); } function stub(obj: any, key: string) { try { Object.defineProperty(obj, key, { configurable: false, get() { return deny; }, set() { /* ignore attempts to restore */ }, }); } catch { try { obj[key] = deny; } catch { /* non-writable in this runtime — already safe */ } } } /** The capabilities user code must never reach; each becomes a throwing stub. */ export const LOCKED_GLOBALS = [ "fetch", "XMLHttpRequest", "WebSocket", "EventSource", // importScripts: the worker is a fully bundled module — nothing legitimate // needs it after boot, so it is denied outright. "importScripts", "indexedDB", "caches", "localStorage", "sessionStorage", ] as const; /** * Replace every network/storage capability on `g` with a throwing stub. * Exported (and unit-tested against a fake global) so the exact lockdown the * worker applies is what the negative tests verify. */ export function applyLockdown(g: any): void { for (const key of LOCKED_GLOBALS) stub(g, key); if (g.navigator) stub(g.navigator, "sendBeacon"); } /** The denied-access sentinel, exported for tests to match the thrown message. */ export const LOCKDOWN_DENIED_MESSAGE = DENIED; // Auto-apply to the worker global on import (import order in sandbox.worker.ts // guarantees this runs before the engine module is evaluated). applyLockdown(globalThis as any); export const LOCKDOWN_ACTIVE = true;