cliclaw 의 보안 취약점을 발견하셨다면 공개 GitHub 이슈를 생성하지 마시고 다음 경로로 알려주세요:
- GitHub Security Advisory: https://github.com/choiyounggi/cliclaw/security/advisories/new
- 또는 maintainer 에게 직접 비공개로 연락
72시간 이내에 첫 응답을 드립니다.
cliclaw 는 단일 신뢰 사용자의 macOS 머신에서 운영되는 봇을 가정합니다. 이 trust boundary 안에서:
- 신뢰: 봇이 spawn 하는 4 코딩 CLI (claude / codex / pi / gemini) 및 그들의 자격증명
- 신뢰:
allowedUserIds에 등록된 Telegram user_id 의 모든 입력 - 반신뢰: 외부에서 채팅에 보낸 사진/문서 (자동 다운로드 후 path traversal 만 방어, 내용은 신뢰)
- 불신: 익명 Telegram 메시지 (allowedUserIds 외 사용자 — 즉시 거부)
allowedUserIds: fail-closed. 빈 배열이면 모든 메시지 거부.config.json: chmod 600 (init 자동). 토큰 평문 저장.
- 모든 subprocess 호출이
Bun.spawn([bin, ...args])exec form — shell 미경유, prompt 의 shell metacharacter 무관. - 위험 Bash 명령(
rm -rf,git push --force, DROP, kubectl delete, AWS delete-, sudo,curl|sh, ssh prd- 등):safety on시 텔레그램 confirm gate 로 다시 확인. - 민감 파일 (
~/.ssh/**,~/.aws/**,.env*,*.pem,id_rsa*등):safety on시 Claude 의 Read 도구가 거부.
- 로그 redaction:
bot.log/bot.err작성 전 Telegram bot token, npm token, GitHub PAT 자동 마스킹. - 이미지 다운로드:
workspace/uploads/<chatId>/<msgId>.<ext>— chat-scoped, 확장자 sanitize, path traversal 방어. - 로그 로테이션: bot.log / audit.jsonl / bot.err 모두 size-bounded.
- TLS 인터셉터 (Zscaler, Forticlient 등) 자동 탐지 →
cliclaw init의 Step 4 에서 사용자 확인 → plist의NODE_EXTRA_CA_CERTS영속화.
- 채팅별 sliding window (기본 30/min) — auto-forwarder/loop 차단.
- 봇 토큰 = 호스트 셸 동급의 자격증명. 유출 시 BotFather
/revoke즉시. allowedUserIds좁게 유지. 다른 사용자 추가는 신중히.codex.sandbox를danger-full-access로 바꾸지 말 것. 봇 토큰 하나로 호스트 전체 노출.gemini.approvalMode: "yolo"옵트인 시 이해 후 결정. 모든 도구 자동 승인 = 호스트 전체 노출.safety off는 본인 환경에 외부 가드(pre-bash-guard, EDR)가 있을 때만. 평소엔safety on유지.config.json백업: Time Machine 등 백업이 안전한 위치에 있는지 확인. 평문 토큰이 그대로 들어감.
- 위험 패턴은 정규식 기반 — 100% 분류 불가.
- Gemini 의 위험 명령은 자체
approvalMode에만 의존 (bash-confirm IPC 미통합). - 사진 외 첨부 처리 안 함.
- macOS only — Linux/Windows 미지원.
The Telegram confirm gate (lib/danger-patterns.ts + bin/bash-confirm.ts) is a
safety net, not a sandbox. It exists to catch obviously destructive
one-liners typed (or generated) while you're away from the keyboard — it does
not bound what a compromised or misdirected agent can ultimately do.
- It matches the literal Bash command text against regexes, not executed
semantics. One level of indirection defeats it:
bash script.sh— wherescript.shcontainsrm -rf ...— never surfacesrm -rfin the text the gate inspects.echo <base64> | base64 -d | sh— the dangerous command only exists after decoding, at execution time.- Command text assembled at runtime (string concatenation, variable
expansion,
eval) can land in the shell without ever appearing as a literal dangerous pattern.
- Treat it as a prompt-injection-adjacent tripwire, not an execution boundary. A model that is tricked (via prompt injection or otherwise) into using one of the indirections above will not be stopped by this gate.
- The layered defenses that actually bound damage live below the gate,
not in it:
- Codex's
workspace-writesandbox (never setcodex.sandboxtodanger-full-access— see the recommended-practices list above). - Claude's Read-tool deny rules for sensitive files (
~/.ssh/**,~/.aws/**,.env*, etc.) undersafety on. - Keeping
safety onso the confirm gate runs at all for the patterns it does catch. - OS-level guards (EDR,
pre-bash-guardhooks) where present on your machine — the gate's patterns intentionally overlap with these and defer to them when both are active.
- Codex's
- Gemini currently bypasses the confirm gate entirely. Gemini does not
integrate with cliclaw's
bash-confirmIPC, so its ownapprovalModeis the only shell-level defense for Gemini sessions. Theauto_editdefault still prompts for shell/destructive actions inside Gemini itself, but opting intogemini.approvalMode: "yolo"removes even that — see item 4 in the recommended-practices list above.
| 날짜 | 검토자 | 결과 |
|---|---|---|
| 2026-05-14 | 내부 | Medium 3건 → v0.7.0 에서 모두 해소 (log redaction, Gemini default, Claude deny rules). 잔여 위험 모두 Low 또는 설계 의도. |