-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* v1 - sandbox node * v1 - sandbox node * v1 - sandbox node * v1 - sandbox node * v1 - sandbox node --------- Co-authored-by: yatchiya <yarab@gmail.com>
- Loading branch information
Showing
35 changed files
with
1,638 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM node:20-alpine | ||
WORKDIR /app | ||
COPY package*.json ./ | ||
RUN npm ci --only=production | ||
COPY dist ./dist | ||
CMD ["node", "dist/index.js"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# SecureNodeJsCodeEnclave | ||
|
||
## Project Overview | ||
|
||
**SecureNodeJsCodeEnclave** is an advanced system designed to create a secure execution environment for running untrusted JavaScript/TypeScript code in Node.js. It provides isolated execution of multiple files, allows for the installation of specified npm packages within a controlled context, and ensures robust security measures to prevent unauthorized access or malicious activities. | ||
|
||
## Features | ||
|
||
- **Isolated Execution:** Run untrusted JavaScript/TypeScript code securely in isolated environments. | ||
- **Controlled NPM Package Installation:** Install and manage npm packages in a controlled, secure manner. | ||
- **Security Measures:** Employs various security features to prevent unauthorized access and mitigate potential threats. | ||
- **Extensible and Configurable:** Easily extendable to support additional tools and configurable to meet diverse security needs. | ||
|
||
## Project Structure | ||
|
||
```plaintext | ||
secure-nodejs-code-enclave/ | ||
├── Dockerfile | ||
├── examples | ||
│ └── tools | ||
│ ├── code_generator.json | ||
│ └── text-summerize.json | ||
├── jest.config.js | ||
├── package.json | ||
├── package-lock.json | ||
├── README.md | ||
├── src | ||
│ ├── ai-tools | ||
│ │ ├── code-generator.ts | ||
│ │ └── text-summerize.ts | ||
│ ├── core | ||
│ │ ├── enclave.ts | ||
│ │ ├── file-manager.ts | ||
│ │ ├── package-manager.ts | ||
│ │ └── virtual-fs.ts | ||
│ ├── index.ts | ||
│ ├── security | ||
│ │ ├── resource-limiter.ts | ||
│ │ └── sandbox.ts | ||
│ ├── templates | ||
│ │ ├── code_generator.yaml | ||
│ │ └── text-summerize.yaml | ||
│ ├── __tests__ | ||
│ │ ├── enclave.test.ts | ||
│ │ ├── file-manager.test.ts | ||
│ │ ├── package-manager.test.ts | ||
│ │ └── sandbox.test.ts | ||
│ ├── types.ts | ||
│ └── utils | ||
│ ├── error-handler.ts | ||
│ ├── execute_tool_schema.ts | ||
│ ├── logger.ts | ||
│ ├── parse_argument.ts | ||
│ ├── process_tool_schema.ts | ||
│ └── tools.ts | ||
├── test | ||
│ ├── integration | ||
│ │ └── enclave-workflow.test.ts | ||
│ ├── security | ||
│ │ └── sandbox-escape.test.ts | ||
│ └── unit | ||
│ ├── enclave.test.ts | ||
│ ├── file-manager.test.ts | ||
│ └── package-manager.test.ts | ||
├── tsconfig.json | ||
└── tree.txt | ||
``` | ||
|
||
## Installation | ||
To set up the project locally, follow these steps: | ||
|
||
Clone the repository: | ||
``` | ||
git clone https://github.com/yourusername/SecureNodeJsCodeEnclave.git | ||
cd SecureNodeJsCodeEnclave | ||
``` | ||
|
||
Install dependencies: | ||
``` | ||
npm install | ||
``` | ||
|
||
Build the project: | ||
|
||
``` | ||
npm run build | ||
``` | ||
|
||
Usage : | ||
|
||
## Running code securely: | ||
|
||
You can use the core enclave.ts to run untrusted JavaScript/TypeScript code securely by following the provided examples in the examples directory. | ||
|
||
## Example commands: | ||
|
||
To execute a template file securely : | ||
|
||
``` | ||
npm run build | ||
npm start -- --file "./examples/tools/text-summerize.json" | ||
``` | ||
## Configuring security settings: | ||
|
||
Modify the settings in src/security/sandbox.ts to adjust the security parameters such as memory limits, execution time, etc. | ||
|
||
|
||
## Contributing | ||
We welcome contributions! Please follow these steps: | ||
|
||
Fork the repository. | ||
Create a new branch: | ||
``` | ||
git checkout -b feature/your-feature-name. | ||
``` | ||
Make your changes and commit them: | ||
```git commit -m 'Add some feature'. | ||
Push to the branch: git push origin feature/your-feature-name | ||
```. | ||
Open a pull request. | ||
## License | ||
This project is licensed under the MIT License - see the LICENSE file for details. | ||
## Acknowledgments | ||
Special thanks to the contributors who have helped build this project. | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"tool": "python-code-generator", | ||
"params": { | ||
"language": "Python", | ||
"task_description": "🐍 Generate a snake game", | ||
"requirements": "🍎 The game should have a snake that moves around the screen and eats food" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"tool": "text-summerizer", | ||
"params": { | ||
"file_url": "https://www.quantalogic.app/blogs/introduction", | ||
"max_words": 150 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = { | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
roots: ['<rootDir>/src'], | ||
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], | ||
moduleFileExtensions: ['ts', 'js', 'json', 'node'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
{ | ||
"name": "secure-nodejs-code-enclave", | ||
"version": "1.0.0", | ||
"description": "A secure execution environment for untrusted JavaScript/TypeScript code", | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"build": "tsc", | ||
"start": "node dist/index.js", | ||
"start_example": "node dist/index_example.js", | ||
"test": "jest --detectOpenHandles", | ||
"test:watch": "jest --watch", | ||
"test:coverage": "jest --coverage", | ||
"start:server": "node dist/index.js --server" | ||
}, | ||
"dependencies": { | ||
"@types/js-yaml": "^4.0.9", | ||
"@vitalets/google-translate-api": "^9.2.0", | ||
"axios": "^1.7.5", | ||
"body-parser": "^1.20.2", | ||
"dotenv": "^16.4.5", | ||
"escodegen": "^2.1.0", | ||
"esprima": "^4.0.1", | ||
"express": "^4.19.2", | ||
"js-yaml": "^4.1.0", | ||
"natural": "^8.0.1", | ||
"openai": "^4.56.1", | ||
"qllm-lib": "^3.2.1", | ||
"uuid": "^8.3.2", | ||
"vm2": "^3.9.11", | ||
"yaml": "^2.5.0", | ||
"yargs": "^17.5.1", | ||
"zod": "^3.23.8" | ||
}, | ||
"devDependencies": { | ||
"@types/body-parser": "^1.19.5", | ||
"@types/escodegen": "^0.0.10", | ||
"@types/esprima": "^4.0.6", | ||
"@types/express": "^4.17.21", | ||
"@types/jest": "^27.5.2", | ||
"@types/node": "^16.18.106", | ||
"@types/uuid": "^8.3.4", | ||
"@types/yargs": "^17.0.33", | ||
"jest": "^27.5.1", | ||
"ts-jest": "^27.1.5", | ||
"typescript": "^4.9.5" | ||
}, | ||
"jest": { | ||
"preset": "ts-jest", | ||
"testEnvironment": "node", | ||
"testMatch": [ | ||
"**/__tests__/**/*.ts", | ||
"**/?(*.)+(spec|test).ts" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Enclave } from '../../src/core/enclave'; | ||
import { EnclaveConfig } from '../../src/types'; | ||
|
||
jest.setTimeout(30000); // Increase global timeout to 30 seconds | ||
|
||
describe('Enclave', () => { | ||
let enclave: Enclave; | ||
const mockConfig: EnclaveConfig = { | ||
cacheDir: './test-cache', | ||
sandboxConfig: { rootDir: './test-sandbox' }, | ||
resourceLimits: { maxExecutionTime: 1000, maxMemory: 10 * 1024 * 1024 }, | ||
loggerConfig: { debugMode: false } | ||
}; | ||
|
||
beforeEach(() => { | ||
enclave = new Enclave(mockConfig); | ||
}); | ||
|
||
afterEach(async () => { | ||
await enclave.cleanup(); | ||
}); | ||
|
||
test('should initialize with correct status', () => { | ||
expect(enclave.getStatus()).toBe('initialized'); | ||
}); | ||
|
||
test('should prepare files and packages', async () => { | ||
const files = [{ name: 'test.js', content: 'console.log("Hello");' }]; | ||
const packages = ['lodash']; | ||
|
||
await enclave.prepare(files, packages); | ||
expect(enclave.getStatus()).toBe('prepared'); | ||
}, 30000); // Increase timeout for this specific test to 30 seconds | ||
|
||
test('should execute code', async () => { | ||
const files = [{ name: 'test.js', content: '__lastExpression = 2 + 2;' }]; | ||
await enclave.prepare(files, []); | ||
const result = await enclave.execute('test.js'); | ||
expect(result).toBe(4); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { FileManager } from '../core/file-manager'; | ||
import * as fs from 'fs/promises'; | ||
import * as path from 'path'; | ||
|
||
describe('FileManager', () => { | ||
let fileManager: FileManager; | ||
const tempDir = './test-temp'; | ||
|
||
beforeEach(() => { | ||
fileManager = new FileManager(tempDir); | ||
}); | ||
|
||
afterEach(async () => { | ||
await fs.rm(tempDir, { recursive: true, force: true }); | ||
}); | ||
|
||
test('should write and read file', async () => { | ||
const fileName = 'test.js'; | ||
const content = 'console.log("Hello");'; | ||
|
||
await fileManager.writeFile(fileName, content); | ||
const readContent = await fileManager.readFile(fileName); | ||
|
||
expect(readContent).toBe(content); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { PackageManager } from '../core/package-manager'; | ||
import * as fs from 'fs/promises'; | ||
import * as path from 'path'; | ||
|
||
describe('PackageManager', () => { | ||
let packageManager: PackageManager; | ||
const tempDir = './test-temp'; | ||
const cacheDir = './test-cache'; | ||
|
||
beforeEach(() => { | ||
packageManager = new PackageManager(tempDir, cacheDir); | ||
}); | ||
|
||
afterEach(async () => { | ||
await fs.rm(tempDir, { recursive: true, force: true }); | ||
await fs.rm(cacheDir, { recursive: true, force: true }); | ||
}); | ||
|
||
test('should resolve package versions', async () => { | ||
const packages = ['lodash']; | ||
const versions = await packageManager.resolvePackageVersions(packages); | ||
expect(versions).toHaveProperty('lodash'); | ||
expect(typeof versions.lodash).toBe('string'); | ||
}, 30000); // Add timeout here as well | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Sandbox } from '../../src/security/sandbox'; | ||
import { SandboxConfig } from '../../src/types'; | ||
|
||
describe('Sandbox', () => { | ||
let sandbox: Sandbox; | ||
|
||
beforeEach(() => { | ||
const config: SandboxConfig = { rootDir: './test-sandbox' }; | ||
sandbox = new Sandbox(config, './test-temp'); | ||
}); | ||
|
||
test('should run code in sandbox', async () => { | ||
const result = await sandbox.run('__lastExpression = 2 + 2'); | ||
expect(result).toBe(4); | ||
}); | ||
|
||
test('should handle multi-line code', async () => { | ||
const code = ` | ||
let x = 10; | ||
let y = 20; | ||
__lastExpression = x + y; | ||
`; | ||
const result = await sandbox.run(code); | ||
expect(result).toBe(30); | ||
}); | ||
|
||
test('should handle async code', async () => { | ||
const code = ` | ||
async function test() { | ||
return new Promise(resolve => setTimeout(() => resolve(42), 100)); | ||
} | ||
__lastExpression = await test(); | ||
`; | ||
const result = await sandbox.run(code); | ||
expect(result).toBe(42); | ||
}); | ||
}); |
Oops, something went wrong.