# ModuleResolver _(no submodules)_ ## Purpose `ModuleResolver` is the gatekeeper between user code and the host's module surface. It maintains an allowlist of modules the sandbox may consult, refuses to register anything on the denylist (`fs`, `net`, `child_process`, `cluster`, `dgram`, `dns`, `http`, `https`, `http2`, `tls`, `worker_threads`, `process`, `os`, `path`, `readline`, `repl`, `vm`), and ships three built-in safe modules (`Math`, `JSON`, `Date`) auto-loaded when their names appear in the allowed list. The resolver is the only place in the package where module names are reasoned about. Engines consume `resolver.getModules()` and inject the returned exports into the execution context; they never reason about names directly. This makes the security boundary auditable in one file rather than spread across four engine implementations. ## Features - Hard-coded denylist of 17 dangerous Node module names. - Three built-in safe modules with curated exports. - `register` / `unregister` for custom modules. - `isBlocked` / `isAllowed` / `getBlockedModules` introspection helpers. - `BLOCKED_MODULES` and `BUILTIN_SAFE_MODULES` exported for downstream composition. ## Usage: Basic ```ts import { ModuleResolver } from "@suaveplan/sandbox/module-resolver"; const resolver = new ModuleResolver(["Math"]); resolver.register({ name: "config", exports: { factor: 21 } }); console.log(resolver.getModules().length); // 2 ``` ## Usage: Advanced Surface the denylist to a UI that shows users why their module registration was rejected: ```ts import { BLOCKED_MODULES, ModuleResolver, } from "@suaveplan/sandbox/module-resolver"; function offerSuggestions(name: string): string { if (BLOCKED_MODULES.has(name)) { return `"${name}" is denylisted — use the sandbox's host bridge instead.`; } return ""; } ``` ## API Reference - `new ModuleResolver(allowedNames?: readonly string[])`. - `register(module: SandboxModule): void` — throws `SandboxError(BLOCKED_MODULE)`. - `unregister(name: string): boolean`. - `getModules(): readonly SandboxModule[]`. - `isBlocked(name: string): boolean`. - `isAllowed(name: string): boolean`. - `getBlockedModules(): readonly string[]`. - `BLOCKED_MODULES: ReadonlySet`. - `BUILTIN_SAFE_MODULES: Readonly SandboxModule>>`. ## Implementation Notes The denylist is hard-coded rather than configurable because it lists Node intrinsics whose mere presence inside a sandbox compromises isolation regardless of whether the engine is a vm context, a worker, or a child process. The `BUILTIN_SAFE_MODULES` factory returns a fresh module per call so custom rebinding by one sandbox does not leak into another sharing the resolver constructor.