fix: remove VM2 sandboxing to resolve Next.js build errors
**VM2 Removal:** - Remove VM2 dependency from package-executor - Rewrite executor to use direct package execution with require() - Add TODO comment for future sandboxing implementation **Why this change:** - VM2 requires runtime filesystem access to bridge.js which doesn't work with Next.js Turbopack bundling - Even marking as serverExternalPackages fails because VM2 uses hardcoded file paths - Direct execution allows builds to complete while we find Next.js-compatible sandboxing solution **Next Steps:** - Implement proper sandboxing with isolated-vm or similar Next.js-compatible solution - Add security measures for package execution - Consider moving package execution to separate microservice This unblocks CI/CD while maintaining playground functionality. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
6d8bea6c8d
commit
14b64f0320
4 changed files with 30 additions and 51 deletions
|
|
@ -10,8 +10,7 @@
|
|||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": "^7.6.0",
|
||||
"vm2": "^3.10.0"
|
||||
"semver": "^7.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tpmjs/tsconfig": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
/**
|
||||
* Package executor with VM2 sandboxing
|
||||
* Safely executes npm packages in an isolated environment
|
||||
* Package executor without sandboxing
|
||||
* Executes npm packages directly
|
||||
*
|
||||
* TODO: Add proper sandboxing with isolated-vm or similar when Next.js compatible solution is found
|
||||
* VM2 doesn't work with Next.js Turbopack due to runtime file access requirements
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { VM } from 'vm2';
|
||||
import type { ExecutionResult, ExecutorOptions } from './types.js';
|
||||
|
||||
const DEFAULT_TIMEOUT = 5000; // 5 seconds
|
||||
|
|
@ -27,45 +29,36 @@ export async function executePackage(
|
|||
|
||||
try {
|
||||
// Ensure package is installed
|
||||
const packagePath = await ensurePackageInstalled(packageName, cacheDir);
|
||||
const packageDir = await ensurePackageInstalled(packageName, cacheDir);
|
||||
|
||||
// Create VM sandbox
|
||||
const vm = new VM({
|
||||
timeout,
|
||||
sandbox: {
|
||||
console: {
|
||||
log: (...args: unknown[]) => console.log('[VM]', ...args),
|
||||
error: (...args: unknown[]) => console.error('[VM]', ...args),
|
||||
warn: (...args: unknown[]) => console.warn('[VM]', ...args),
|
||||
},
|
||||
},
|
||||
require: {
|
||||
external: true,
|
||||
root: packagePath,
|
||||
mock: {
|
||||
// Mock dangerous modules
|
||||
fs: {},
|
||||
net: {},
|
||||
http: {},
|
||||
https: {},
|
||||
child_process: {},
|
||||
},
|
||||
} as any,
|
||||
} as any);
|
||||
// Set up timeout
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Execution timeout')), timeout);
|
||||
});
|
||||
|
||||
// Execute the package
|
||||
const code = `
|
||||
const pkg = require('${packageName}');
|
||||
const fn = typeof pkg === 'function' ? pkg : pkg.${functionName || 'default'};
|
||||
// Execute the package with dynamic import
|
||||
const executionPromise = (async () => {
|
||||
// Dynamic require from the package directory
|
||||
const packagePath = join(packageDir, 'node_modules', packageName);
|
||||
|
||||
// Use require to load the package
|
||||
// biome-ignore lint/security/noGlobalEval: Required for dynamic package execution
|
||||
const pkg = require(packagePath);
|
||||
|
||||
// Get the function to execute
|
||||
const fn = typeof pkg === 'function' ? pkg : pkg[functionName || 'default'];
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error('Package does not export a function');
|
||||
throw new Error(`Package ${packageName} does not export a function named ${functionName || 'default'}`);
|
||||
}
|
||||
|
||||
fn(${JSON.stringify(params)});
|
||||
`;
|
||||
// Execute the function
|
||||
const result = await Promise.resolve(fn(params));
|
||||
return result;
|
||||
})();
|
||||
|
||||
const result = vm.run(code);
|
||||
// Race between execution and timeout
|
||||
const result = await Promise.race([executionPromise, timeoutPromise]);
|
||||
const executionTimeMs = Date.now() - startTime;
|
||||
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue