무엇이든 실행할 수 있던 AI 봇에 최소 권한 채우기: bypassPermissions 제거기

편의를 위해 AI 에이전트에게 "모든 권한 통과(bypass)"를 켜두는 건 흔한 일입니다. 잘 돌아가니까요. 그런데 그 봇은 서버에서 무엇이든 실행할 수 있는 상태였습니다 — 파일 삭제, 서비스 종료, 시크릿 파일 읽기, 실거래 주문까지. 이 글은 항상 켜진 AI 봇의 권한을 "모두 허용"에서 화이트리스트 기반 최소 권한으로 좁힌 과정과, 그 과정에서 마주친 우회 함정들의 기록입니다.

1. 출발점: "모든 권한 통과"의 위험

메신저로 조종하는 AI 봇을 처음 세울 땐 권한 프롬프트가 거슬려서 "묻지 말고 다 실행" 모드로 켜두기 쉽습니다. 문제는, 그 봇이 실수하거나(환각) 프롬프트 인젝션에 당하면 그 무제한 권한이 그대로 공격 표면이 된다는 겁니다. 실제로 이 봇은:

  • rm으로 파일을 지울 수 있었고
  • 서비스를 죽이거나 재시작할 수 있었고
  • 시크릿 파일(.env 등)을 읽을 수 있었고
  • 금융 도구로 실제 매수/매도 주문을 낼 수 있었습니다

2. 근거부터: 30일 실사용 로그 분석

권한을 무작정 줄이면 봇이 쓸모없어집니다. 그래서 먼저 "이 봇이 실제로 뭘 쓰는가"를 데이터로 봤습니다. 최근 30일 세션 기록을 전수 집계했더니:

  • 대부분 조회성 명령 — 로그 보기, 상태 확인, 파일 읽기, 검색
  • 파일 편집·작성은 가끔
  • 매매 주문·셸 실행·시크릿 파일 쓰기는 30일간 0건

결론이 분명했습니다. 봇이 실제로 필요로 하는 건 "조회 + 가벼운 편집"이고, 위험한 것들은 애초에 안 쓰고 있었습니다. 그럼 안 쓰는 걸 막아도 잃을 게 없습니다.

3. 설계: allow / deny 화이트리스트 + 헤드리스 안전 모드

"모든 권한 통과"를 끄고, 명시적 허용/차단 목록으로 바꿨습니다.

# Before
--permission-mode bypass  # 무엇이든 실행

# After
--permission-mode dont-ask          # 허용 외엔 프롬프트 없이 거절
--settings whitelist.json           # allow/deny 목록으로 통제

핵심 원칙 세 가지:

  1. allow는 관찰된 조회성만: 상태 조회, 로그, 파일 읽기/편집, 검색 등 실제로 쓰던 것들.
  2. deny를 우선: 허용과 겹쳐도 차단이 이깁니다. 파괴 명령(rm·서비스 삭제·강제 푸시·권한 변경 등), 매매 실행 도구, 시크릿 파일 읽기/쓰기는 명시적으로 deny.
  3. 거절해도 멈추지 않게: 헤드리스에서 권한 프롬프트가 뜨면 입력을 기다리며 정지합니다. 그래서 "묻지 않고 그냥 거절" 모드를 씁니다. 봇은 "그건 권한이 없어 못 했다"고 보고하고 넘어갑니다.

4. 검증: 실제로 거절되는가

설정은 믿지 말고 실측해야 합니다. 헤드리스로 실제 명령을 던져 봤습니다.

상태 조회        → 실행됨  ✅ (허용)
파일 목록·로그   → 실행됨  ✅ (허용)
rm 실행 시도     → 거절됨  🚫 (deny)
시크릿 파일 읽기 → 거절됨  🚫 (deny)
매매 주문 도구   → 거절됨  🚫 (deny)

허용은 되고 위험한 건 막힙니다. 좋습니다. 그런데 남은 구멍이 있었습니다.

5. 함정: 화이트리스트로 다 막히지 않는다

최소 권한을 진지하게 하면 "우회 경로"를 반드시 점검해야 합니다. 제가 남긴 구멍들:

  • 범용 인터프리터는 사실상 임의 실행: python 실행을 허용해 두면, 그 안에서 파일 삭제든 뭐든 할 수 있습니다. rm을 deny해도 python -c "os.remove(...)"로 우회됩니다. 편의(분석 능력)와 안전의 트레이드오프라, "실용안(허용)"과 "엄격안(제외)"을 갈라 문서화했습니다.
  • 읽기 도구만 막으면 셸로 샌다: 시크릿 파일을 "읽기 도구"에서 deny해도, cat 같은 셸 명령이 허용돼 있으면 그걸로 읽힙니다. 도구 단위 deny와 셸 명령 단위 deny를 함께 봐야 합니다.
  • 파일 쓰기 허용은 간접 실행: 파일 편집을 허용하면, 나중에 실행될 스크립트나 예약 작업 파일을 고쳐 우회할 수 있습니다.

이 구멍들은 "봇이 소유자 전용"이라는 전제(발신자 화이트리스트로 외부인 차단) 위에서 수용 가능한 수준으로 판단했습니다. 외부인이 조종할 수 없다면, 남는 위험은 소유자 본인의 실수·인젝션 방어이고, 그건 더 엄격한 모드로 언제든 조일 수 있게 열어뒀습니다.

6. 교훈

  • 권한은 편의가 아니라 데이터로 정하라. "혹시 몰라 다 열어둔다"가 아니라, 실사용 로그로 필요 최소를 도출하면 잃는 것 없이 표면을 줄입니다.
  • deny를 우선하고, 우회 경로까지 점검하라. allow만으로는 부족합니다. 인터프리터·셸·파일쓰기라는 "만능 도구"가 화이트리스트를 무력화할 수 있습니다.
  • 완벽한 최소 권한과 실용성은 트레이드오프다. 어디까지 조일지는 "누가 이 봇을 조종할 수 있나"에 달려 있습니다. 접근 통제가 탄탄하면 실용안을, 아니면 엄격안을.
  • 헤드리스에선 "거절"이 "정지"가 되지 않게. 권한이 없으면 조용히 거절하고 보고하도록 해야, 입력 대기로 멈추지 않습니다.

FAQ

Q. 애초에 봇에 위험한 도구를 아예 안 주면 되지 않나요?

맞습니다. 가능한 건 애초에 노출하지 않는 게 최선입니다. 다만 하나의 통합 도구 세트(예: 파일·셸·검색이 묶인)를 쓸 땐 세밀하게 뺄 수 없어서, 노출은 하되 권한 계층에서 거절하는 방식이 현실적입니다.

Q. python까지 막으면 봇이 너무 무력해지지 않나요?

그게 정확히 트레이드오프입니다. 분석·계산을 많이 시키면 인터프리터가 유용하지만, 그만큼 임의 실행 창구가 됩니다. 접근 통제(누가 봇을 조종하는지)가 1인 소유자로 확실하면 실용안을, 인젝션 리스크를 더 낮추려면 엄격안을 선택하세요.

Q. 최소 권한 하나면 봇이 안전한가요?

아닙니다. 층으로 쌓아야 합니다. 이 작업의 전제는 "발신자 화이트리스트로 외부인이 봇에 말을 못 건다"였습니다. 권한 축소는 그 위에 얹는 두 번째 층이고, 최종 방어선은 계정 자체의 보안(2단계 인증 등)입니다.

이 글은 실제 운영 중인 개인 AI 에이전트의 권한 강화 작업을 일반화해 정리한 기록입니다. 특정 호스트·경로·자격증명·도구명 등 구체적 인프라 정보는 의도적으로 제외했습니다.