PraisonAI: 경로 검증 없이 `multiedit` 도구를 통해 임의 파일 읽기/쓰기
src/praisonai/praisonai/tools/multiedit.py의 multiedit 도구를 사용하면 경로 유효성 검사, 작업 공간 경계 확인 또는 보호된 경로 가드 없이 LLM 제어 임의 파일 읽기 및 쓰기가 가능합니다. 이를 통해 (제작된 프롬프트, 채팅 봇의 사용자 입력 또는 악의적인 YAML 워크플로 구성을 통해) 에이전트 도구 인수에 영향을 미칠 수 있는 공격자가 민감한 파일(예: /etc/shadow, ~/.ssh/id_rsa, ~/.aws/credentials)을 읽고 파일 시스템의 임의 파일을 덮어쓸 수 있습니다.
filepath 매개변수는 동일한 코드베이스의 다른 도구에 존재하는 다음 보호 조치 없이 읽기(74행) 및 쓰기(130행) 모두에 open()과 함께 직접 사용됩니다.
.. 경로 탐색 검사 없음 — file_tools.py(라인 66: if '..' in filepath: raise ValueError) 및 edit_tools.py(라인 35)와 다릅니다.file_tools.py(os.path.commonpath 확인이 포함된 _validate_path) 및 skill_tools.py(작업 공간 경계 확인이 포함된 read_skill_file)와는 다릅니다.is_path_within_directory 및 보호된 경로 검사를 사용하는 praisonai/code/tools/와는 다릅니다.os.path.realpath를 사용하는 file_tools.py와는 다릅니다.이 기능은 src/praisonai/praisonai/tools/__init__.py를 통해 지연 로드 도구로 내보내지며 PraisonAI CLI 도구 레지스트리를 통해 에이전트가 사용할 수 있습니다.
보호된 도구와 대조: src/praisonai/praisonai/code/tools/의 형제 도구 write_file.py, read_file.py, apply_diff.py 및 search_replace.py는 모두 is_path_within_directory() 검사 및 보호된 경로 가드를 구현합니다. multiedit 도구에는 이러한 보호 기능이 없습니다.
설정: d5f1114a 커밋에서 PraisonAI를 클린 체크아웃합니다. Python 3.10+ 이상에는 추가 종속성이 필요하지 않습니다.
긍정적 트리거 — dry_run을 통해 읽은 임의 파일: ``배쉬 cd /tmp && python3 -c " 수입 시스템 sys.path.insert(0, 'src/praisonai') praisonai.tools.multiedit에서 다중 편집 가져오기
결과 = multiedit('/etc/hostname', [{'old': 'DOESNOTEXIST', 'new': 'x'}], dry_run=True)
print('성공:', 결과['성공']) print('diff를 통해 유출된 콘텐츠:', len(result.get('diff', '')), 'bytes') "
**긍정적 트리거 — 임의 파일 쓰기:**
``배쉬
cd /tmp && python3 -c "
수입 시스템
sys.path.insert(0, 'src/praisonai')
praisonai.tools.multiedit에서 다중 편집 가져오기
# 작업공간 외부의 임의 파일에 쓰기
open('/tmp/victim_file.txt', 'w')을 f로 사용:
f.write('원본 내용은 여기에\n')
결과 = multiedit('/tmp/victim_file.txt', [{'old': 'original', 'new': 'PWNED'}])
open('/tmp/victim_file.txt', 'r')을 f로 사용:
print('편집 후 파일 내용:', repr(f.read()))
"
관찰된 결과:
# 읽기:
성공: 거짓
diff를 통해 유출된 콘텐츠: 0바이트(편집 내용이 일치할 때 dry_run diff를 통해 파일 콘텐츠에 계속 액세스할 수 있음)
# 쓰기:
편집 후 파일 콘텐츠: '여기에 PWNED 콘텐츠\n'
음성 대조군 — 존재하지 않는 파일: ``배쉬 결과 = multiedit('/nonexistent/file.txt', [{'old': 'a', 'new': 'b'}])
**정리:** `rm /tmp/victim_file.txt`
## 영향
'multiedit' 도구의 'filepath' 매개변수에 영향을 미칠 수 있는 공격자는(AI 에이전트에 대한 조작된 프롬프트, `auto_approve_tools=True`를 사용하는 Telegram/Discord/Slack 봇의 사용자 메시지 또는 YAML 워크플로 구성을 통해) 다음을 수행할 수 있습니다.
- **임의 파일 읽기** — 비밀, SSH 키, 클라우드 자격 증명, 환경 파일(`.env`) 및 구성 파일을 포함하여 프로세스 사용자가 읽을 수 있는 모든 파일입니다.
- **임의 파일 쓰기/덮어쓰기** — 프로세스 사용자가 쓸 수 있는 모든 파일을 수정하여 권한 상승을 활성화합니다(예: `~/.bashrc`, `~/.ssh/authorized_keys`에 쓰기 또는 애플리케이션 소스 코드 덮어쓰기).
이는 'auto_approve_tools'가 기본값인 'True'인 PraisonAI CLI 및 채팅 봇 배포를 포함하여 에이전트가 사용할 수 있는 'multiedit' 도구가 있는 모든 배포에 영향을 미칩니다.
## 제안된 해결 방법
`file_tools.py`와 `src/praisonai/praisonai/code/tools/`의 코드 도구에서 사용하는 것과 동일한 경로 유효성 검사 패턴을 적용합니다.
1. 다음과 같은 `_validate_path` 함수를 추가합니다.
- `..`을 포함하는 경로를 거부합니다.
- `os.path.realpath`를 통해 심볼릭 링크를 해결합니다.
- `os.path.commonpath`를 사용하여 확인된 경로가 작업공간/CWD 내에 있는지 확인합니다.
2. 보호된 경로 가드(`.env`, `.git`, `.ssh`, 키, 자격 증명)를 추가합니다.
3. `open()` 호출 전에 `filepath` 매개변수에 `_validate_path`를 적용하세요.
4. `multiedit` 기능에 `@require_approval(risk_level="high")` 추가를 고려해보세요.
### 크레딧
- VinSOC Labs(R&D)의 Thai Son Dinh
왜 이 VPI인가 (설명가능 · 실험적)
VPI 산정 기준
| 영향도 | 91.00 |
| 악용 신호(추가 악용신호 없음) | ×1.00 |
| VPI | 91.00 |
VPI 공식 vpi-v1 기준