함수 생성자를 통한 npm PraisonAI codeMode 샌드박스 탈출
게시된 npm 패키지 'praisonai'는 'codeMode'라는 TypeScript 내장 도구를 내보냅니다. 패키지는 이 도구를 샌드박스 환경에서 코드를 실행하는 것으로 설명하고 해당 기능을 sandbox: true로 표시하며 공개 도구 외관을 통해 등록합니다.
구현 시 격리 경계가 생성되지 않습니다. 작은 정규식 차단 목록을 적용하고 일반 JavaScript 객체 내에서 process 및 require를 undefine으로 설정한 다음 호스트 프로세스 new Function 생성자를 사용하여 공격자가 제어하는 코드를 실행합니다.
``텍스트
const fn = new Function('sandbox', with (sandbox) { ${code} });
const 결과 = fn(샌드박스);
이는 호스트 V8 컨텍스트에서 실행되기 때문에 `codeMode` 내부의 코드는 JavaScript 프로토타입 체인을 사용하여 실제 `Function` 생성자를 복구할 수 있습니다.
``텍스트
({}).constructor.constructor('반환 프로세스')()
일반 CommonJS 애플리케이션 스크립트에서 복구된 process 객체는 process.mainModule.require를 노출합니다. 이는 명시적인 require('fs') 및 require('child_process') 제어를 우회하고 샌드박스로 예상되는 코드에서 호스트 파일 시스템 액세스 및 하위 프로세스 실행을 허용합니다.
현재 헤드 소스에 따르면 'codeMode'는 내장 패키지 도구이며 명시적으로 샌드박스 경계를 광고합니다.
``텍스트 src/praisonai-ts/src/tools/builtins/code-mode.ts 13: 설명: '샌드박스 환경에서 다른 도구를 가져오고 사용할 수 있는 코드를 실행합니다', 24: 기능: { 25: 샌드박스: 참, 26: 코드: 참, 28: 패키지명: 'praisonai', 85: 설명: '가져온 도구에 접근하여 샌드박스 환경에서 코드를 실행합니다. 파일을 작성하고, 코드를 실행하고, 결과를 얻으세요.',
동일한 파일은 정확한 소스 코드 패턴의 차단 목록으로 보안을 구현합니다.
``텍스트
src/praisonai-ts/src/tools/builtins/code-mode.ts
108: const 차단 패턴 = [
109: /require\s*\(\s*['"]child_process['"]\s*\)/,
110: /require\s*\(\s*['"]fs['"]\s*\)/,
111: /import\s+.*from\s+['"]자식 프로세스['"]/,
112: /프로세스\.exit/,
113: /평가\s*\(/,
그런 다음 일반 객체의 이름을 숨겨 위험한 전역을 숨기려고 합니다.
``텍스트 src/praisonai-ts/src/tools/builtins/code-mode.ts 168: 프로세스: 정의되지 않음, 169: 요구: 정의되지 않음,
마지막으로 'new Function' 및 'with (sandbox)'를 사용하여 호스트 프로세스에서 신뢰할 수 없는 코드를 실행합니다.
``텍스트
src/praisonai-ts/src/tools/builtins/code-mode.ts
187: const fn = 새로운 함수(
188: '샌드박스',
189: `(샌드박스) { ${code} }`
190: );
191: const 결과 = fn(샌드박스);
이것은 샌드박스가 아닙니다. 'new Function'은 별도의 보안 컨텍스트를 생성하지 않으며 변수 섀도잉은 일반 JavaScript 객체를 통해 도달할 수 있는 생성자에 대한 액세스를 제거하지 않습니다.
이 도구는 공개 npm SDK를 통해 접근할 수 있습니다.
``텍스트 src/praisonai-ts/src/index.ts 117: airweaveSearch,코드모드,
src/praisonai-ts/src/tools/tools.ts 104: // 코드 모드 105: Registry.register(CODE_MODE_METADATA, createCodeModeTool as ToolFactory); 167: // 코드 모드 168: 코드모드: (config?: CodeModeConfig) => 코드모드(config),
### 이것이 의도한 동작이 아닌 이유
이것은 단지 "codeMode가 코드를 실행하기 때문에 사용자가 코드를 실행할 수 있다"는 것이 아닙니다. 취약점은 샌드박스로 명시적으로 설명되고 노출되는 코드가 의도한 제한을 벗어날 수 있다는 것입니다.
구현 자체는 의도된 보안 경계가 존재함을 증명합니다.
- `CODE_MODE_METADATA.capability.sandbox`는 `true`입니다.
- 도구 설명에는 샌드박스 환경에서 실행된다고 나와 있습니다.
- `fs` 및 `child_process`에 대한 직접 액세스는 명시적으로 차단됩니다.
- 'process' 및 'require'는 명시적으로 '정의되지 않음'으로 숨겨집니다.
- `allowNetwork`의 기본값은 `false`입니다. 그리고
- 구성에는 'blockedTools', 'allowedPaths', 'timeoutMs' 및 'maxMemoryMb'와 같은 보안 관련 컨트롤이 포함되어 있습니다.
PoV는 의도된 제한이 순진한 페이로드에는 작동하지만 표준 JavaScript 프로토타입 체인 이스케이프에는 실패함을 보여줍니다.
PraisonAI의 공식 JavaScript 및 TypeScript 문서에서는 npm 패키지를 `npm install praisonai`와 함께 설치되는 프로덕션 지원 에이전트 프레임워크로 설명합니다. 공개 PraisonAI 권고는 사용자/LLM 제공 코드가 청구된 샌드박스에서 호스트 실행으로 전환될 때 유사한 Python 샌드박스 이스케이프를 위험으로 평가합니다.
## PoV
PoV는 게시된 npm 패키지 버전을 임시 프로젝트에 설치하고 실제 CommonJS 스크립트 파일에서 실행됩니다. 일반 Node 애플리케이션은 `process.mainModule.require`를 노출하므로 파일에서 실행하는 것이 중요합니다. `node -e` 또는 stdin이 항상 해당 배포 형태를 재현하는 것은 아닙니다.
로컬 복제 체크아웃에서 실행:
``물고기
노드 poc/pov_poc.js 1.7.1
관찰 결과:
``json { "패키지": "프라이소나이", "버전": "1.7.1", "codeModeExported": 사실, "directRequireFsControl": { "stderr": "차단된 패턴이 감지되었습니다: require\s*\(\s*['"]fs['"]\s*\)", "종료코드": 1, "성공": 거짓, "error": "코드에 보안을 위해 차단된 패턴이 포함되어 있습니다." }, "directChildProcessControl": { "stderr": "차단된 패턴이 감지되었습니다: require\s*\(\s*['"]child_process['"]\s*\)", "종료코드": 1, "성공": 거짓, "error": "코드에 보안을 위해 차단된 패턴이 포함되어 있습니다." }, "escapedProcessEnv": { "출력": "poc", "종료코드": 0, "성공": 사실 }, "escapedFilesystem": { "출력": "fs-ok", "종료코드": 0, "성공": 사실 }, "escapedCommand": { "출력": "poc", "종료코드": 0, "성공": 사실 } }
해석:
- 직접 `require('fs')`가 차단되었습니다.
- 직접 `require('child_process')`가 차단되었습니다.
- 함수 생성자 페이로드는 호스트 '프로세스'를 복구합니다.
- 이스케이프된 프로세스는 호스트 환경 변수를 읽습니다.
- 이스케이프된 프로세스는 `fs`를 가져옵니다. 그리고
- 이스케이프된 프로세스는 `child_process`를 가져오고 무해한 `printf`를 실행합니다.
PoV는 npm 패키지 설치 후 LLM 제공업체 또는 외부 서비스에 연결하지 않습니다. 호스트 파일을 수정하거나 파괴적인 명령을 실행하지 않습니다.
## PoC
위의 PoV 섹션에는 로컬 재생 명령, 입력 및 결정적인 출력이 포함됩니다.
## 영향
'codeMode'에 코드를 제공할 수 있는 공격자는 광고된 샌드박스를 탈출하고 Node.js PraisonAI 프로세스의 권한으로 실행할 수 있습니다.
현실적인 진입점은 다음과 같습니다.
- 'codeMode'를 최종 사용자에게 에이전트 도구로 노출하는 애플리케이션
- 프롬프트 제어 콘텐츠가 '코드' 매개변수에 도달하는 LLM/도구 호출 흐름
- 내장된 `codeMode` 도구를 호출 가능하게 만드는 MCP 또는 도구 레지스트리 통합 또는
- 사용자 또는 모델 생성 JavaScript를 안전하게 실행하기 위해 'codeMode'를 사용하는 다중 테넌트 서비스입니다.
탈출 후 영향은 다음과 같습니다.
- API 키 및 서비스 토큰을 포함한 프로세스 환경 변수 읽기
- 노드 프로세스에 사용 가능한 파일 읽기
- `child_process`를 사용하여 하위 프로세스 생성;
- 호스트 파일 시스템 API를 통해 파일을 쓰거나 수정합니다. 그리고
- 호스트 프로세스를 종료하거나 리소스를 소모합니다.
### 심각도
제안된 심각도: 심각.
근거:
- `AV`: `codeMode`는 지정된 에이전트/도구 표면이며 도구 호출을 사용자 또는 LLM 제어 워크플로우에 노출하는 표준 에이전트 애플리케이션의 네트워크를 통해 연결할 수 있습니다.
- `AC`: 단일 코드 페이로드로 충분합니다.
- 'PR': 공격자는 에이전트/도구 흐름에 코드 또는 프롬프트 제어 콘텐츠를 제출할 수 있는 능력이 필요합니다.
- `UI`: 도구가 호출되면 추가 사용자 상호 작용이 필요하지 않습니다.
- `S`: 실행은 알려진 샌드박스 보안 범위에서 호스트 Node.js 프로세스로 넘어갑니다.
- `C`: 호스트 파일과 환경 변수를 읽을 수 있습니다.
- `I`: 호스트 하위 프로세스 및 파일 시스템 API에 접근할 수 있습니다.
- `A`: 이스케이프된 코드는 프로세스를 종료하거나 호스트 리소스를 소비할 수 있습니다.
## 제안된 수정 사항
호스트 프로세스 '새 함수'와 소스 코드 차단 목록을 샌드박스로 사용하지 마세요.
권장 수정 방향:
1. 실제 격리 경계가 존재할 때까지 npm `codeMode`를 안전하지 않은 것으로 비활성화하거나 명확하게 표시합니다.
2. 제한된 사용자, 최소 환경, 임시 작업 디렉터리, 상속된 비밀 없음 및 허용된 도구 호출에 대한 명시적 IPC를 사용하여 별도의 OS 프로세스, 컨테이너, 작업자 격리 또는 유사한 경계에서 신뢰할 수 없는 코드를 실행합니다.
3. 소스 문자열을 스캔하는 대신 해당 경계에서 `allowNetwork`, `allowedPaths`, `timeoutMs`, `maxMemoryMb`, `allowedTools` 및 `blockedTools`를 적용합니다.
4. 신뢰할 수 없는 코드에 대해 `node:vm`에만 의존하지 마십시오. Node.js 문서에는 `vm` 모듈이 보안 메커니즘이 아니라고 명시적으로 명시되어 있습니다.
5. 다음에 대한 회귀 테스트를 추가합니다.
- 직접 `require('fs')` 및 `require('child_process')` 차단된 컨트롤을 사용합니다.
- `({}).constructor.constructor('return process')()`가 차단되었습니다.
- `process.mainModule.require('fs')`를 사용할 수 없습니다.
- `process.mainModule.require('child_process')`를 사용할 수 없습니다.
- 명시적으로 전달되지 않는 한 호스트 환경 변수를 사용할 수 없습니다. 그리고
- 도구 호출 IPC는 허용된 도구에 대해 계속 작동합니다.
실제 샌드박스가 존재하기 전에 관리자가 긴급 완화가 필요한 경우 호출자가 전체 Node 프로세스에 액세스할 수 있다는 명확한 문서와 함께 '안전하지 않은 호스트 JS 실행'을 선택하지 않는 한 'codeMode' 실행을 거부하세요.
## 영향을 받는 패키지/버전
- 저장소: `MervinPraison/PraisonAI`
- 생태계: `npm`
- 패키지 : `praisonai`
- 구성 요소: `src/praisonai-ts/src/tools/builtins/code-mode.ts`
- 현재 npm 버전 확인됨: `1.7.1`
- 새로 고쳐진 `원산지/메인` 확인됨: `1ad58ca02975ff1398efeda694ea2ab78f20cf3e`
확인된 영향 범위:
``텍스트
>= 1.4.0, <= 1.7.1
경계:
``텍스트 1.3.6은 codeMode를 내보내지 않으며 dist/tools/builtins/code-mode.js를 제공하지 않습니다.
이 보고서가 작성되는 시점에는 고정된 npm 버전이 알려져 있지 않습니다.
### 버전 스윕
포함된 스윕은 선택된 npm 버전을 설치하고 스크립트 파일에서 동일한 취약한 형태를 실행합니다.
``물고기
노드 poc/version_sweep_poc.js
관찰 결과:
``텍스트 1.3.6: codeModeExported=false, hasDistCodeMode=false 1.4.0: directRequireFsBlocked=true, escapeProcessEnv=true, escapeFilesystem=true, escapeCommand=true 1.5.4: directRequireFsBlocked=true, escapeProcessEnv=true, escapeFilesystem=true, escapeCommand=true 1.6.0: directRequireFsBlocked=true, escapeProcessEnv=true, escapeFilesystem=true, escapeCommand=true 1.7.0: directRequireFsBlocked=true, escapeProcessEnv=true, escapeFilesystem=true, escapeCommand=true 1.7.1: directRequireFsBlocked=true, escapeProcessEnv=true, escapeFilesystem=true, escapeCommand=true
TypeScript 파일의 Git 기록은 1.4.0 통합을 가리킵니다.
``텍스트
56f36e25 feat: 버전을 1.4.0으로 높이고 AI SDK 통합 종속성을 추가합니다.
2bad9a50 feat: 버전을 1.4.0으로 높이고 AI SDK 통합 종속성을 추가합니다.
확인됨:
codeMode, npm, sandbox, new Function, process 및 child_process에 대한 공개 GitHub 권고 검색 결과; 그리고가장 가까운 관련 권고는 Python/PyPI 범위이며 이 npm TypeScript 구현을 다루지 않습니다.
GHSA-qf73-2hrx-xprp / CVE-2026-39888: Python 하위 프로세스 샌드박스의 pip:praisonaiagents execute_code() 프레임 탐색.GHSA-4mr5-g6f9-cfrh / CVE-2026-47392: pip:praisonai Python execute_code() 샌드박스는 print.__self__를 통해 이스케이프됩니다.이 보고서는 다음을 목표로 한다는 점에서 특별합니다.
npm;praisonai;src/praisonai-ts/src/tools/builtins/code-mode.ts;new Function 및 차단 목록/이름 섀도잉 샌드박스; 그리고>= 1.4.0, <= 1.7.1.TypeScript AgentOS 인증 누락(GHSA-9752-mhqh-h34f)에 대한 비공개 npm 보고서가 이미 제출되었습니다. 이는 또한 구별됩니다. 'codeMode' 샌드박스 이스케이프가 아닌 인증되지 않은 HTTP 에이전트 나열/호출을 다루고 있습니다.
왜 이 VPI인가 (설명가능 · 실험적)
VPI 산정 기준
| 영향도 | 99.00 |
| 악용 신호(추가 악용신호 없음) | ×1.00 |
| VPI | 99.00 |
VPI 공식 vpi-v1 기준