npm PraisonAI SandboxExecutor allowed쉘 체인을 통해 명령 우회
게시된 npm 패키지 praisonai는 SandboxExecutor, CommandValidator 및 sandboxExec를 "제한이 있는 안전한 명령 실행"으로 내보냅니다. allowedCommands가 구성되면 CommandValidator는 명령 문자열의 첫 번째 공백으로 구분된 토큰만 확인합니다. 그런 다음 SandboxExecutor는 전체 원본 문자열을 spawn("sh", ["-c", command])에 전달합니다.
echo만 허용하는 정책을 사용하면 이 직접 명령이 올바르게 거부됩니다.
``쉬 고양이 /tmp/마커
그러나 다음과 같은 연결된 명령이 승인되고 실행됩니다.
``쉬
에코가 허용됩니다. 고양이 /tmp/마커
'cat'이 허용 목록에 없더라도 셸은 'cat'을 실행합니다. 이는 애플리케이션, CLI 워크플로 또는 에이전트 파이프라인이 신뢰도가 낮은 사용자, 프롬프트 또는 모델 출력에 샌드박스 명령 실행을 노출할 때 명령 허용 목록을 우회하고 PraisonAI 프로세스 권한으로 임의의 셸 명령을 실행할 수 있습니다.
PoV는 결정적이며 로컬 전용입니다. 임시 마커 파일만 생성하고 읽습니다.
src/praisonai-ts/src/cli/features/sandbox-executor.ts에서 CommandValidator.validate()는 명령을 정규화하고 첫 번째 공백 토큰만 인증합니다.
``ts const 정규화 = command.toLowerCase().trim();
if (this.allowedCommands) {
const baseCmd = Normalized.split(/\s+/)[0];
if (!this.allowedCommands.includes(baseCmd)) {
return { 유효함: false, 이유: '${baseCmd}' 명령이 허용 목록에 없음 };
}
}
거부 목록은 일반적으로 셸 구분 기호를 거부하지 않습니다. `;와 같은 몇 가지 특정 패턴을 차단합니다. rm`은 아니지만 `; cat`, `&&`, `||`, 백틱, `$()` 또는 개행 문자를 일반 정책 경계로 사용합니다.
그런 다음 `SandboxExecutor.spawn()`은 셸을 통해 수정되지 않은 명령 문자열을 실행합니다.
``ts
const proc = generate('sh', ['-c', 명령], {
cwd: this.config.cwd,
환경,
시간 초과: this.config.timeout,
stdio: ['파이프', '파이프', '파이프']
});
이로 인해 불일치가 발생합니다. 허용 목록은 하나의 명령 토큰을 승인하지만 셸은 전체 문자열을 스크립트로 해석합니다.
게시된 npm:praisonai@1.7.1 dist 파일은 동일한 동작을 유지합니다.
dist/cli/features/sandbox-executor.js는 baseCmd만 확인합니다.dist/cli/features/sandbox-executor.js는 나중에 spawn("sh", ["-c", command])를 호출합니다.dist/index.js는 SandboxExecutor, CommandValidator 및 sandboxExec을 내보냅니다.PraisonAI의 샌드박스 문서에서는 명령 검증, 리소스 제한, 경로 제한, 네트워크 격리 및 실행 격리를 포함하여 AI 생성 명령에 대한 보안 기능으로 샌드박스 실행을 설명합니다. TypeScript 소스에서는 이 구성 요소를 "제한이 있는 안전한 명령 실행"이라고 설명합니다.
allowedCommands: ["echo"]를 사용하면 PraisonAI가 직접 제출할 때 cat <marker>를 올바르게 거부합니다. 이는 의도된 정책이 허용 목록에 없는 실행 파일을 차단하는 것임을 증명합니다. '에코 허용'을 허용하는 동일한 정책; 따라서 cat `는 단순한 허용 구성이 아니라 인증 우회입니다.
로컬 복제 체크아웃에서 실행:
``배쉬 노드 poc/pov_poc.js 1.7.1
예상 출력은 다음과 같습니다.
``json
{
"버전": "1.7.1",
"패키지": "npm:praisonai",
"allowedCommands": ["에코"],
"컨트롤": {
"directCatRejected": 사실,
"benignEchoAllowed": 사실,
"patchedControlRejectsChainedShell": 참
},
"관찰": {
"직접정책": {
"허용": 거짓,
"reason": "허용 목록에 'cat' 명령이 없습니다."
},
"benignPolicy": {
"허용": 사실
},
"chainedPolicy": {
"허용": 사실
},
"체인 실행": {
"성공": 사실,
"stdout": "허용\npoc.7.1",
"표준 오류": "",
"종료코드": 0
},
"패치컨트롤": {
"양성": {
"허용": 사실
},
"직접": {
"허용": 거짓,
"reason": "허용 목록에 'cat' 명령이 없습니다."
},
"체인": {
"허용": 거짓,
"reason": "실행 전에 쉘 메타 문자가 거부되었습니다"
}
}
},
"취약한": 사실
}
해석:
cat <marker>는 허용 목록에 의해 거부됩니다.에코 허용이 허용됩니다.에코 허용됨; cat <marker>는 동일한 허용 목록에 의해 허용되며 허용 목록에 없는 cat을 실행합니다.에코를 허용합니다.PoV는 npm:praisonai@1.7.1을 임시 프로젝트에 설치하고 임시 마커 파일을 생성한 후 해당 파일만 읽습니다. 라이브 서비스에 접속하거나 파괴적인 명령을 실행하지 않습니다.
위의 PoV 섹션에는 로컬 재생 명령, 입력 및 결정적인 출력이 포함됩니다.
신뢰도가 낮은 사용자, 프롬프트 또는 모델 출력이 SandboxExecutor 또는 sandboxExec로 전송된 명령 문자열에 영향을 미칠 수 있는 경우 allowedCommands는 의도된 명령 경계를 적용하지 않습니다. 공격자는 허용된 첫 번째 토큰 뒤에 임의의 셸 명령을 추가하고 PraisonAI 프로세스의 권한으로 실행할 수 있습니다.
구체적인 결과는 호스팅 응용 프로그램과 구성된 프로세스 권한에 따라 다르지만 파일 읽기 또는 수정, 로컬 도구 호출, 사용 가능한 자격 증명 사용 또는 서비스 거부 유발 등이 포함될 수 있습니다.
이 보고서는 npm PraisonAI가 이를 기본 네트워크 서비스로 노출한다고 주장하지 않습니다. 이는 안전한 명령 실행을 위해 명시적으로 설계된 내보낸 TypeScript API의 라이브러리 수준 샌드박스/허용 목록 우회입니다.
권장 심각도: 높음.
근거:
AV: 일반적인 배포 패턴은 네트워크를 통해 에이전트 프롬프트 또는 명령 자동화를 노출하는 애플리케이션입니다.AC: 공격자는 허용된 명령으로 시작하는 명령 문자열을 유도하거나 제출하기만 하면 됩니다.UI: 명령이 실행기에 도달하면 운영자 작업이 필요하지 않습니다.S: PraisonAI 호스팅 프로세스에 영향이 있습니다.C/I/A: 임의의 셸 명령은 프로세스 권한에 따라 기밀성, 무결성 및 가용성에 영향을 미칠 수 있습니다.관리자가 로컬 CLI 사용만을 평가한다면 AV:L이 합리적일 수 있습니다. 이 API를 기반으로 구축된 인증되지 않은 공개 프롬프트 또는 명령 엔드포인트를 평가하는 경우 'PR:N'이 합리적일 수 있습니다.
정책 확인 사용자 문자열을 셸에 전달하지 마세요.
권장사항:
{ command, args }를 전달하거나 쉘 인식 파서를 사용하여 명령 문자열을 argv로 구문 분석하도록 요구합니다.sh -c 대신 spawn(command, args, { shell: false }) / execFile()로 실행합니다.allowedCommands를 적용합니다.;, &&, ||, |, 백틱, $(), 개행, 리디렉션)를 거부하십시오.allowedCommands: ["echo"]가 echo ok를 허용하지만 cat marker, echo ok'는 거부함을 입증하는 회귀 테스트를 추가합니다. 고양이 마커, 에코 ok && 고양이 마커, 에코 ok | 고양이 마커.MervinPraison/PraisonAInpm:praisonaiSandboxExecutor1ad58ca02975ff1398efeda694ea2ab78f20cf3ev4.6.581.7.1제안된 영향 범위:
``텍스트 npm:praisonai >= 1.2.3, <= 1.7.1
선택한 버전 스윕:
- `1.0.0`: 선택한 테스트 환경에서는 패키지 메인이 필요할 수 없습니다.
- `1.2.0`, `1.2.1`, `1.2.2`: `SandboxExecutor`를 내보내지 않습니다.
- `1.2.3`: 취약함.
- `1.2.4`: 취약함.
- `1.3.0`: 취약함.
- `1.3.6`: 취약함.
- `1.4.0`: 취약함.
- `1.5.0`: 취약함.
- `1.5.4`: 취약함.
- `1.6.0`: 취약함.
- `1.7.0`: 취약함.
- `1.7.1`: 취약함.
## 자문 이력
이는 알려지거나 이전에 제출된 PraisonAI 문제와는 다릅니다.
- `GHSA-r4f2-3m54-pp7q`는 PyPI `SubprocessSandbox` `shell=True` 및 차단 목록 우회를 다룹니다.
- `GHSA-2763-cj5r-c79m`은 PyPI `praisonai` OS 명령 주입을 다룹니다.
- `GHSA-v7px-3835-7gjx`는 PyPI `memory/hooks.py` 셸 주입을 다룹니다.
- 'GHSA-4wr3-f4p3-5wjh'는 Python 에이전트 도구 승인 허용 목록 조작을 다룹니다.
- `GHSA-4mr5-g6f9-cfrh`는 PyPI/Python `execute_code` 샌드박스 이스케이프를 다룹니다.
- `GHSA-9qhq-v63v-fv3j`는 Python 명령 삽입에 대한 불완전한 수정 사항을 다룹니다.
- `GHSA-vmmj-pfw7-fjwp`는 npm `codeMode` 호스트 프로세스 `new Function` 샌드박스 이스케이프를 다룹니다.
npm TypeScript `SandboxExecutor`, `CommandValidator`, `allowedCommands` 또는 `sh -c` 셸 체인 근본 원인이 뒤따르는 첫 번째 토큰 허용 목록을 다루는 눈에 띄는 로컬 또는 GitHub 권고는 없습니다.
왜 이 VPI인가 (설명가능 · 실험적)
VPI 산정 기준
| 영향도 | 88.00 |
| 악용 신호(추가 악용신호 없음) | ×1.00 |
| VPI | 88.00 |
VPI 공식 vpi-v1 기준