@secure-exec/core 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +7 -0
  3. package/dist/bridge/active-handles.d.ts +21 -0
  4. package/dist/bridge/active-handles.js +60 -0
  5. package/dist/bridge/child-process.d.ts +90 -0
  6. package/dist/bridge/child-process.js +606 -0
  7. package/dist/bridge/fs.d.ts +281 -0
  8. package/dist/bridge/fs.js +2151 -0
  9. package/dist/bridge/index.d.ts +10 -0
  10. package/dist/bridge/index.js +41 -0
  11. package/dist/bridge/module.d.ts +75 -0
  12. package/dist/bridge/module.js +308 -0
  13. package/dist/bridge/network.d.ts +249 -0
  14. package/dist/bridge/network.js +1416 -0
  15. package/dist/bridge/os.d.ts +13 -0
  16. package/dist/bridge/os.js +256 -0
  17. package/dist/bridge/polyfills.d.ts +2 -0
  18. package/dist/bridge/polyfills.js +11 -0
  19. package/dist/bridge/process.d.ts +86 -0
  20. package/dist/bridge/process.js +938 -0
  21. package/dist/bridge-setup.d.ts +6 -0
  22. package/dist/bridge-setup.js +9 -0
  23. package/dist/bridge.js +11538 -0
  24. package/dist/esm-compiler.d.ts +14 -0
  25. package/dist/esm-compiler.js +68 -0
  26. package/dist/fs-helpers.d.ts +23 -0
  27. package/dist/fs-helpers.js +41 -0
  28. package/dist/generated/isolate-runtime.d.ts +19 -0
  29. package/dist/generated/isolate-runtime.js +21 -0
  30. package/dist/generated/polyfills.d.ts +82 -0
  31. package/dist/generated/polyfills.js +82 -0
  32. package/dist/index.d.ts +30 -0
  33. package/dist/index.js +25 -0
  34. package/dist/isolate-runtime/apply-custom-global-policy.js +54 -0
  35. package/dist/isolate-runtime/apply-timing-mitigation-freeze.js +44 -0
  36. package/dist/isolate-runtime/apply-timing-mitigation-off.js +14 -0
  37. package/dist/isolate-runtime/bridge-attach.js +29 -0
  38. package/dist/isolate-runtime/bridge-initial-globals.js +246 -0
  39. package/dist/isolate-runtime/eval-script-result.js +8 -0
  40. package/dist/isolate-runtime/global-exposure-helpers.js +36 -0
  41. package/dist/isolate-runtime/init-commonjs-module-globals.js +28 -0
  42. package/dist/isolate-runtime/override-process-cwd.js +8 -0
  43. package/dist/isolate-runtime/override-process-env.js +8 -0
  44. package/dist/isolate-runtime/require-setup.js +650 -0
  45. package/dist/isolate-runtime/set-commonjs-file-globals.js +36 -0
  46. package/dist/isolate-runtime/set-stdin-data.js +10 -0
  47. package/dist/isolate-runtime/setup-dynamic-import.js +64 -0
  48. package/dist/isolate-runtime/setup-fs-facade.js +48 -0
  49. package/dist/module-resolver.d.ts +25 -0
  50. package/dist/module-resolver.js +264 -0
  51. package/dist/package-bundler.d.ts +36 -0
  52. package/dist/package-bundler.js +497 -0
  53. package/dist/python-runtime.d.ts +16 -0
  54. package/dist/python-runtime.js +45 -0
  55. package/dist/runtime-driver.d.ts +62 -0
  56. package/dist/runtime-driver.js +1 -0
  57. package/dist/runtime.d.ts +31 -0
  58. package/dist/runtime.js +69 -0
  59. package/dist/shared/api-types.d.ts +71 -0
  60. package/dist/shared/api-types.js +1 -0
  61. package/dist/shared/bridge-contract.d.ts +302 -0
  62. package/dist/shared/bridge-contract.js +82 -0
  63. package/dist/shared/console-formatter.d.ts +22 -0
  64. package/dist/shared/console-formatter.js +157 -0
  65. package/dist/shared/constants.d.ts +3 -0
  66. package/dist/shared/constants.js +3 -0
  67. package/dist/shared/errors.d.ts +16 -0
  68. package/dist/shared/errors.js +21 -0
  69. package/dist/shared/esm-utils.d.ts +28 -0
  70. package/dist/shared/esm-utils.js +97 -0
  71. package/dist/shared/global-exposure.d.ts +38 -0
  72. package/dist/shared/global-exposure.js +406 -0
  73. package/dist/shared/in-memory-fs.d.ts +42 -0
  74. package/dist/shared/in-memory-fs.js +341 -0
  75. package/dist/shared/permissions.d.ts +38 -0
  76. package/dist/shared/permissions.js +283 -0
  77. package/dist/shared/require-setup.d.ts +6 -0
  78. package/dist/shared/require-setup.js +9 -0
  79. package/dist/types.d.ts +206 -0
  80. package/dist/types.js +1 -0
  81. package/package.json +107 -0
@@ -0,0 +1,157 @@
1
+ export const DEFAULT_CONSOLE_SERIALIZATION_BUDGET = {
2
+ maxDepth: 6,
3
+ maxKeys: 50,
4
+ maxArrayLength: 50,
5
+ maxOutputLength: 4096,
6
+ };
7
+ function normalizeBudget(budget) {
8
+ const defaults = {
9
+ maxDepth: 6,
10
+ maxKeys: 50,
11
+ maxArrayLength: 50,
12
+ maxOutputLength: 4096,
13
+ };
14
+ const clamp = (value, fallback) => {
15
+ if (!Number.isFinite(value))
16
+ return fallback;
17
+ const normalized = Math.floor(value);
18
+ return normalized > 0 ? normalized : fallback;
19
+ };
20
+ return {
21
+ maxDepth: clamp(budget.maxDepth, defaults.maxDepth),
22
+ maxKeys: clamp(budget.maxKeys, defaults.maxKeys),
23
+ maxArrayLength: clamp(budget.maxArrayLength, defaults.maxArrayLength),
24
+ maxOutputLength: clamp(budget.maxOutputLength, defaults.maxOutputLength),
25
+ };
26
+ }
27
+ function safeStringifyConsoleValueWithBudget(value, budget) {
28
+ const suffix = "...[Truncated]";
29
+ const clampOutput = (text) => {
30
+ if (text.length <= budget.maxOutputLength) {
31
+ return text;
32
+ }
33
+ if (budget.maxOutputLength <= suffix.length) {
34
+ return suffix.slice(0, budget.maxOutputLength);
35
+ }
36
+ return (text.slice(0, budget.maxOutputLength - suffix.length) + suffix);
37
+ };
38
+ if (value === null)
39
+ return "null";
40
+ if (value === undefined)
41
+ return "undefined";
42
+ const valueType = typeof value;
43
+ if (valueType !== "object") {
44
+ if (valueType === "bigint") {
45
+ return `${String(value)}n`;
46
+ }
47
+ return clampOutput(String(value));
48
+ }
49
+ const rootObject = value;
50
+ const skipFastPath = (Array.isArray(rootObject) &&
51
+ rootObject.length > budget.maxArrayLength) ||
52
+ (!Array.isArray(rootObject) &&
53
+ Object.keys(rootObject).length > budget.maxKeys);
54
+ if (!skipFastPath) {
55
+ try {
56
+ const quickSerialized = JSON.stringify(value);
57
+ if (quickSerialized !== undefined) {
58
+ return clampOutput(quickSerialized);
59
+ }
60
+ }
61
+ catch {
62
+ // Fall back to circular-safe and budget-aware serialization.
63
+ }
64
+ }
65
+ const seen = new WeakSet();
66
+ const depthByObject = new WeakMap();
67
+ const replacer = function (key, current) {
68
+ if (typeof current === "bigint") {
69
+ return `${String(current)}n`;
70
+ }
71
+ if (typeof current !== "object" || current === null) {
72
+ return current;
73
+ }
74
+ const currentObject = current;
75
+ if (seen.has(currentObject)) {
76
+ return "[Circular]";
77
+ }
78
+ seen.add(currentObject);
79
+ let depth = 0;
80
+ if (key !== "") {
81
+ const parent = this;
82
+ if (typeof parent === "object" && parent !== null) {
83
+ depth = (depthByObject.get(parent) ?? 0) + 1;
84
+ }
85
+ }
86
+ depthByObject.set(currentObject, depth);
87
+ if (depth > budget.maxDepth) {
88
+ return "[MaxDepth]";
89
+ }
90
+ if (Array.isArray(currentObject)) {
91
+ if (currentObject.length <= budget.maxArrayLength) {
92
+ return currentObject;
93
+ }
94
+ const trimmed = currentObject.slice(0, budget.maxArrayLength);
95
+ trimmed.push("[Truncated]");
96
+ return trimmed;
97
+ }
98
+ const keys = Object.keys(currentObject);
99
+ if (keys.length <= budget.maxKeys) {
100
+ return currentObject;
101
+ }
102
+ const trimmed = {};
103
+ for (let i = 0; i < budget.maxKeys; i += 1) {
104
+ const keyName = keys[i];
105
+ trimmed[keyName] = currentObject[keyName];
106
+ }
107
+ trimmed["[Truncated]"] = `${keys.length - budget.maxKeys} key(s)`;
108
+ return trimmed;
109
+ };
110
+ try {
111
+ const serialized = JSON.stringify(value, replacer);
112
+ if (serialized === undefined) {
113
+ return clampOutput(String(value));
114
+ }
115
+ return clampOutput(serialized);
116
+ }
117
+ catch {
118
+ return clampOutput(String(value));
119
+ }
120
+ }
121
+ /** Serialize a single value with circular reference detection and budget limits. */
122
+ export function safeStringifyConsoleValue(value, rawBudget) {
123
+ return safeStringifyConsoleValueWithBudget(value, normalizeBudget(rawBudget));
124
+ }
125
+ /** Format an array of console arguments into a single space-separated string. */
126
+ export function formatConsoleArgs(args, rawBudget) {
127
+ const budget = normalizeBudget(rawBudget);
128
+ const formatted = [];
129
+ for (let i = 0; i < args.length; i += 1) {
130
+ formatted.push(safeStringifyConsoleValueWithBudget(args[i], budget));
131
+ }
132
+ return formatted.join(" ");
133
+ }
134
+ /**
135
+ * Generate isolate-side JavaScript that installs a `globalThis.console` shim.
136
+ * The shim serializes arguments using the budget and forwards them to host
137
+ * bridge references (`_log` / `_error`) via `applySync`.
138
+ */
139
+ export function getConsoleSetupCode(budget = DEFAULT_CONSOLE_SERIALIZATION_BUDGET) {
140
+ const normalizedBudget = normalizeBudget(budget);
141
+ return `
142
+ // tsx/esbuild may emit __name(...) wrappers inside function source strings.
143
+ const __name = (value) => value;
144
+ const __consoleBudget = ${JSON.stringify(normalizedBudget)};
145
+ const normalizeBudget = ${normalizeBudget.toString()};
146
+ const safeStringifyConsoleValueWithBudget = ${safeStringifyConsoleValueWithBudget.toString()};
147
+ const safeStringifyConsoleValue = ${safeStringifyConsoleValue.toString()};
148
+ const formatConsoleArgs = ${formatConsoleArgs.toString()};
149
+
150
+ globalThis.console = {
151
+ log: (...args) => _log.applySync(undefined, [formatConsoleArgs(args, __consoleBudget)]),
152
+ error: (...args) => _error.applySync(undefined, [formatConsoleArgs(args, __consoleBudget)]),
153
+ warn: (...args) => _error.applySync(undefined, [formatConsoleArgs(args, __consoleBudget)]),
154
+ info: (...args) => _log.applySync(undefined, [formatConsoleArgs(args, __consoleBudget)]),
155
+ };
156
+ `;
157
+ }
@@ -0,0 +1,3 @@
1
+ /** Matches GNU `timeout` convention where 124 indicates execution timed out. */
2
+ export declare const TIMEOUT_EXIT_CODE = 124;
3
+ export declare const TIMEOUT_ERROR_MESSAGE = "CPU time limit exceeded";
@@ -0,0 +1,3 @@
1
+ /** Matches GNU `timeout` convention where 124 indicates execution timed out. */
2
+ export const TIMEOUT_EXIT_CODE = 124;
3
+ export const TIMEOUT_ERROR_MESSAGE = "CPU time limit exceeded";
@@ -0,0 +1,16 @@
1
+ /** Node-compatible system error shape with code, errno, path, and syscall. */
2
+ export interface SystemError extends Error {
3
+ code?: string;
4
+ errno?: number | string;
5
+ path?: string;
6
+ syscall?: string;
7
+ }
8
+ /** Build a system error with the given POSIX error code (ENOENT, EACCES, etc.). */
9
+ export declare function createSystemError(code: string, message: string, details?: {
10
+ path?: string;
11
+ syscall?: string;
12
+ }): SystemError;
13
+ /** Create a permission-denied error matching Node's EACCES format. */
14
+ export declare function createEaccesError(op: string, path?: string, reason?: string): SystemError;
15
+ /** Create a "function not implemented" error for unsupported operations. */
16
+ export declare function createEnosysError(op: string, path?: string): SystemError;
@@ -0,0 +1,21 @@
1
+ /** Build a system error with the given POSIX error code (ENOENT, EACCES, etc.). */
2
+ export function createSystemError(code, message, details) {
3
+ const err = new Error(message);
4
+ err.code = code;
5
+ if (details?.path)
6
+ err.path = details.path;
7
+ if (details?.syscall)
8
+ err.syscall = details.syscall;
9
+ return err;
10
+ }
11
+ /** Create a permission-denied error matching Node's EACCES format. */
12
+ export function createEaccesError(op, path, reason) {
13
+ const suffix = path ? ` '${path}'` : "";
14
+ const reasonSuffix = reason ? `: ${reason}` : "";
15
+ return createSystemError("EACCES", `EACCES: permission denied, ${op}${suffix}${reasonSuffix}`, { path, syscall: op });
16
+ }
17
+ /** Create a "function not implemented" error for unsupported operations. */
18
+ export function createEnosysError(op, path) {
19
+ const suffix = path ? ` '${path}'` : "";
20
+ return createSystemError("ENOSYS", `ENOSYS: function not implemented, ${op}${suffix}`, { path, syscall: op });
21
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Detect if code uses ESM syntax.
3
+ */
4
+ export declare function isESM(code: string, filePath?: string): boolean;
5
+ /**
6
+ * Transform dynamic import() calls to __dynamicImport() calls.
7
+ */
8
+ export declare function transformDynamicImport(code: string): string;
9
+ /**
10
+ * Extract static import specifiers from transformed code.
11
+ */
12
+ export declare function extractDynamicImportSpecifiers(code: string): string[];
13
+ /**
14
+ * Convert CJS module to ESM-compatible wrapper.
15
+ */
16
+ /**
17
+ * Wrap CommonJS code in an ESM-compatible module that exports `module.exports`
18
+ * as the default export plus any statically-detectable named exports.
19
+ */
20
+ export declare function wrapCJSForESM(code: string): string;
21
+ export declare function wrapCJSForESMWithModulePath(code: string, modulePath: string): string;
22
+ /**
23
+ * Scan CJS code for `module.exports.X =`, `exports.X =`, and
24
+ * `Object.defineProperty(exports, 'X', ...)` patterns to discover named exports
25
+ * that can be re-exported from the ESM wrapper.
26
+ */
27
+ declare function extractCjsNamedExports(code: string): string[];
28
+ export { extractCjsNamedExports };
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Detect if code uses ESM syntax.
3
+ */
4
+ export function isESM(code, filePath) {
5
+ if (filePath?.endsWith(".mjs"))
6
+ return true;
7
+ if (filePath?.endsWith(".cjs"))
8
+ return false;
9
+ const hasImport = /^\s*import\s*(?:[\w{},*\s]+\s*from\s*)?['"][^'"]+['"]/m.test(code) ||
10
+ /^\s*import\s*\{[^}]*\}\s*from\s*['"][^'"]+['"]/m.test(code);
11
+ const hasExport = /^\s*export\s+(?:default|const|let|var|function|class|{)/m.test(code) ||
12
+ /^\s*export\s*\{/m.test(code);
13
+ return hasImport || hasExport;
14
+ }
15
+ /**
16
+ * Transform dynamic import() calls to __dynamicImport() calls.
17
+ */
18
+ export function transformDynamicImport(code) {
19
+ return code.replace(/(?<![a-zA-Z_$])import\s*\(/g, "__dynamicImport(");
20
+ }
21
+ /**
22
+ * Extract static import specifiers from transformed code.
23
+ */
24
+ export function extractDynamicImportSpecifiers(code) {
25
+ const regex = /__dynamicImport\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
26
+ const specifiers = new Set();
27
+ for (const match of code.matchAll(regex)) {
28
+ specifiers.add(match[1]);
29
+ }
30
+ return Array.from(specifiers);
31
+ }
32
+ /**
33
+ * Convert CJS module to ESM-compatible wrapper.
34
+ */
35
+ /**
36
+ * Wrap CommonJS code in an ESM-compatible module that exports `module.exports`
37
+ * as the default export plus any statically-detectable named exports.
38
+ */
39
+ export function wrapCJSForESM(code) {
40
+ const modulePath = "/<cjs-module>.cjs";
41
+ return wrapCJSForESMWithModulePath(code, modulePath);
42
+ }
43
+ function getModuleDir(path) {
44
+ const normalized = path.replace(/\\/g, "/");
45
+ const lastSlash = normalized.lastIndexOf("/");
46
+ if (lastSlash <= 0) {
47
+ return "/";
48
+ }
49
+ return normalized.slice(0, lastSlash);
50
+ }
51
+ export function wrapCJSForESMWithModulePath(code, modulePath) {
52
+ const moduleDir = getModuleDir(modulePath);
53
+ const namedExports = extractCjsNamedExports(code)
54
+ .filter((name) => name !== "default" && name !== "__esModule")
55
+ .map((name) => {
56
+ const localName = `__cjs_named_${name}`;
57
+ return `const ${localName} = __cjs?.${name};\nexport { ${localName} as ${name} };`;
58
+ })
59
+ .join("\n");
60
+ return `
61
+ const __filename = ${JSON.stringify(modulePath)};
62
+ const __dirname = ${JSON.stringify(moduleDir)};
63
+ const require = (name) => globalThis._requireFrom(name, __dirname);
64
+ const module = { exports: {} };
65
+ const exports = module.exports;
66
+ ${code}
67
+ const __cjs = module.exports;
68
+ export default __cjs;
69
+ export const __cjsModule = true;
70
+ ${namedExports}
71
+ `;
72
+ }
73
+ /**
74
+ * Scan CJS code for `module.exports.X =`, `exports.X =`, and
75
+ * `Object.defineProperty(exports, 'X', ...)` patterns to discover named exports
76
+ * that can be re-exported from the ESM wrapper.
77
+ */
78
+ function extractCjsNamedExports(code) {
79
+ const names = new Set();
80
+ const add = (name) => {
81
+ if (!/^[A-Za-z_$][\w$]*$/.test(name)) {
82
+ return;
83
+ }
84
+ names.add(name);
85
+ };
86
+ for (const match of code.matchAll(/\bmodule\.exports\.([A-Za-z_$][\w$]*)\s*=/g)) {
87
+ add(match[1]);
88
+ }
89
+ for (const match of code.matchAll(/\bexports\.([A-Za-z_$][\w$]*)\s*=/g)) {
90
+ add(match[1]);
91
+ }
92
+ for (const match of code.matchAll(/\bObject\.defineProperty\(\s*(?:module\.)?exports\s*,\s*["']([^"']+)["']/g)) {
93
+ add(match[1]);
94
+ }
95
+ return Array.from(names).sort();
96
+ }
97
+ export { extractCjsNamedExports };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Classification for globals the runtime installs on the isolate's `globalThis`.
3
+ *
4
+ * - `hardened`: non-writable, non-configurable. Prevents sandbox code from
5
+ * replacing bridge callbacks or lifecycle hooks.
6
+ * - `mutable-runtime-state`: writable per-execution state (module cache,
7
+ * stdin data, CJS module/exports wrappers) that must be reset between runs.
8
+ */
9
+ export type CustomGlobalClassification = "hardened" | "mutable-runtime-state";
10
+ export interface CustomGlobalInventoryEntry {
11
+ name: string;
12
+ classification: CustomGlobalClassification;
13
+ rationale: string;
14
+ }
15
+ export declare const NODE_CUSTOM_GLOBAL_INVENTORY: readonly CustomGlobalInventoryEntry[];
16
+ export declare const HARDENED_NODE_CUSTOM_GLOBALS: string[];
17
+ export declare const MUTABLE_NODE_CUSTOM_GLOBALS: string[];
18
+ interface ExposeGlobalOptions {
19
+ mutable?: boolean;
20
+ enumerable?: boolean;
21
+ }
22
+ /**
23
+ * Define a property on `target` using `Object.defineProperty`.
24
+ * By default the property is non-writable/non-configurable (hardened).
25
+ */
26
+ export declare function exposeGlobalBinding(target: Record<string, unknown>, name: string, value: unknown, options?: ExposeGlobalOptions): void;
27
+ /** Install a hardened (non-writable) global on `globalThis`. */
28
+ export declare function exposeCustomGlobal(name: string, value: unknown): void;
29
+ /** Install a writable global on `globalThis` for per-execution state. */
30
+ export declare function exposeMutableRuntimeStateGlobal(name: string, value: unknown): void;
31
+ /**
32
+ * Inline JavaScript source that provides `exposeCustomGlobal` and
33
+ * `exposeMutableRuntimeStateGlobal` inside the isolate's V8 context.
34
+ * Evaluated by the host after context creation so that bridge/runtime
35
+ * scripts can harden their own globals.
36
+ */
37
+ export declare const ISOLATE_GLOBAL_EXPOSURE_HELPER_SOURCE = "(() => {\n const exposeGlobalBinding = (name, value, mutable = false) => {\n Object.defineProperty(globalThis, name, {\n value,\n writable: mutable,\n configurable: mutable,\n enumerable: true,\n });\n };\n const exposeCustomGlobal = (name, value) => exposeGlobalBinding(name, value, false);\n const exposeMutableRuntimeStateGlobal = (name, value) =>\n exposeGlobalBinding(name, value, true);\n return {\n exposeCustomGlobal,\n exposeMutableRuntimeStateGlobal,\n };\n})()";
38
+ export {};