본문으로 바로가기
Devpeon
Dev.peon · 개발노동자
Engineering

AI 코딩 · 코딩 에이전트 · 샌드박스 · 권한 관리

AI 에이전트에게 터미널을 맡겨도 될까? 대규모 오픈소스의 권한·승인 설계

AI 코딩 에이전트의 승인 창과 샌드박스는 같은 안전장치가 아닙니다. 세 오픈소스의 코드와 테스트를 통해 파일·네트워크·비밀정보 경계와 팀 적용 방법을 살펴봅니다.

1. 승인 버튼 한 번으로 무엇을 내준 걸까

흔히 마주칠 수 있는 가상 상황부터 떠올려보겠습니다. AI 에이전트에게 “테스트를 실행해 주세요”라고 요청했습니다. 잠시 뒤 터미널 승인 창에 긴 명령이 나타납니다. 앞부분은 익숙한 테스트 명령이지만 뒤에는 패키지 설치와 네트워크 요청이 붙어 있습니다. 급한 마음에 승인하면, 에이전트는 어디까지 할 수 있을까요?

현재 프로젝트만 수정할 수 있을까요? 홈 디렉터리의 파일도 읽을 수 있을까요? 인터넷으로 환경 변수를 보낼 수 있을까요? 승인 창은 이 질문에 모두 답해주지 않습니다.

세 대규모 오픈소스의 공개 코드와 테스트를 살펴보니 안전 설계의 핵심은 “위험한 명령을 잘 분류하는가”보다 한 단계 아래에 있었습니다. 판단을 묻는 승인, 실제 능력을 제한하는 샌드박스, 비밀정보의 흐름을 다루는 데이터 경계를 서로 다른 장치로 설계하는 것입니다.

2. 승인과 샌드박스는 같은 기능이 아닙니다

먼저 세 단어를 나눠야 합니다.

  • 승인은 “이 행동을 실행할지” 결정하는 절차입니다.
  • 샌드박스는 “실행된 프로세스가 무엇을 할 수 있는지” 제한하는 경계입니다.
  • 데이터 경계는 “비밀정보와 명령 출력이 어디로 전달되고 남는지” 통제합니다.

예를 들어 rm -rf ../를 승인 창에서 거부하면 승인 정책이 사고를 막은 것입니다. 반대로 사용자가 실수로 승인했는데도 프로세스가 작업공간 밖을 지우지 못한다면 샌드박스가 막은 것입니다.

둘은 실패 방식도 다릅니다. 승인 정책은 사용자의 피로와 너무 넓은 “항상 허용” 규칙에, 샌드박스는 잘못된 마운트와 비활성화 옵션에 약합니다. 데이터 경계는 더 쉽게 빠집니다. 읽기 전용 모드라도 .env나 SSH 설정을 읽을 수 있다면 위험은 남고, 긴 출력의 원본을 파일에 저장한다면 보존 위험도 따로 판단해야 합니다.

이제 세 프로젝트가 이 세 층을 어떻게 나눴는지 보겠습니다.

3. 특정 오픈소스 A: 능력의 경계를 먼저 정합니다

특정 오픈소스 A는 실행 환경을 크게 읽기 전용, 작업공간 쓰기, 전체 접근으로 구분합니다. 빈 설정을 불러오는 테스트에서는 읽기는 가능하지만 쓰기는 거부되는 내장 읽기 전용 프로필을 확인합니다.

특정 오픈소스 A의 정책 정의와 설정 테스트를 설명하기 위해 이름과 구조를 줄였습니다.

코드 예시실행 흐름
read-only  disk write: deny  network: denyworkspace-write  current workspace: write  network: denydanger-full-access  sandbox restrictions: disabled

작업공간 쓰기 모드도 단순히 “현재 폴더 전체를 수정 가능”으로 끝나지 않습니다. 추가 쓰기 경로를 열더라도 저장소 메타데이터인 .git, 에이전트 설정 폴더, 프로젝트 지침 폴더는 다시 읽기 전용으로 남기는 테스트가 있습니다. 에이전트가 Git Hook이나 자체 권한 설정을 바꿔 다음 실행의 경계를 넓히는 일을 줄이려는 방어입니다.

네트워크는 파일 쓰기와 별도 축입니다. 작업공간에 코드를 쓸 수 있어도 기본 정책에서는 외부 통신이 열리지 않습니다. “코드를 수정하려면 인터넷도 필요하다”는 묶음을 깨고 필요한 능력만 주는 방식입니다.

안전한 명령 하나가 전체 명령을 안전하게 만들지는 않습니다

승인 정책에도 단계가 있습니다. 엄격한 정책은 알려진 읽기 명령만 자동 허용하고 나머지는 사용자에게 묻습니다. 테스트에는 읽기와 변경이 섞인 복합 명령이 등장합니다.

코드 예시SH
cat ./one.txt && touch ./two.txt

앞의 cat이 안전하더라도 뒤의 touch는 파일을 만듭니다. 테스트는 이 명령 전체가 승인 대상으로 남고, 사용자가 거부하면 실패 결과가 에이전트에게 돌아가는지 확인합니다. 명령 문자열의 첫 단어만 보고 허용하면 안 된다는 뜻입니다.

읽기 전용의 한계도 코드에 드러납니다

여기서 중요한 반전이 있습니다. 특정 오픈소스 A의 레거시 읽기 전용 정책은 전체 디스크 읽기가 가능하다고 보고합니다. 쓰기와 네트워크를 막아도 홈 디렉터리의 민감한 파일을 읽는 능력까지 자동으로 사라지는 것은 아닙니다.

셸에 넘길 환경 변수 정책도 기본 상태에서는 이름에 KEY, SECRET, TOKEN이 들어간 변수를 자동 제외하지 않습니다. 필터 기능은 존재하지만 기본 정책이 곧 비밀정보 보호 정책은 아닙니다.

따라서 A에서 직접 확인할 수 있는 강점은 변경 범위와 네트워크 능력을 분리했다는 것입니다. “읽기 전용이므로 모든 비밀정보도 안전하다”는 결론은 공개 코드가 뒷받침하지 않습니다.

4. 특정 오픈소스 B: 정책 엔진 위에 선택형 샌드박스를 올립니다

특정 오픈소스 B는 도구 호출을 allow, ask_user, deny 규칙으로 평가합니다. 기본 규칙은 파일 읽기와 검색 같은 도구를 허용하고, 파일 쓰기와 셸 실행은 대화형 환경에서 사용자에게 묻습니다.

사람이 답할 수 없는 비대화형 실행에서는 동작이 달라집니다. 승인 대기 상태로 멈추는 대신, 원래 질문이 필요했던 쓰기·셸 도구를 거부합니다. 통합 테스트는 읽기 도구는 성공하고 셸 도구는 거부되는지 확인합니다.

특정 오픈소스 B의 기본 정책과 비대화형 테스트를 축약했습니다.

코드 예시TOML
read_tools = "allow"[interactive]write_file = "ask_user"run_shell = "ask_user"[headless]write_file = "deny"run_shell = "deny"

이 기본값은 자동화에서 특히 중요합니다. 승인 UI가 없는 CI나 배치 작업에서 askallow로 바꾸면 편하지만, 사람이 보지 못한 명령이 호스트 권한으로 실행될 수 있습니다. B는 기본 거부를 택하고, 필요한 명령은 사용자가 정책 파일에서 명시적으로 허용하게 합니다.

계획 모드도 완전한 무쓰기는 아닙니다

계획 모드는 먼저 모든 도구를 거부한 뒤 읽기 도구만 다시 엽니다. 다만 계획 결과를 저장하기 위해 지정된 임시 계획 디렉터리의 마크다운 파일은 쓸 수 있습니다.

이 예외는 합리적이지만 표현은 정확해야 합니다. “계획 모드는 어떤 파일도 쓰지 않는다”가 아니라 “소스 변경은 막고 지정된 계획 파일만 쓴다”가 구현에 맞습니다.

또한 사용자와 관리자 정책은 기본 정책보다 높은 계층에서 평가됩니다. 사용자가 명시적으로 셸을 허용하면 비대화형 테스트에서도 실행할 수 있습니다. 대부분의 도구를 자동 허용하는 모드도 별도로 존재합니다. 제한 모드의 이름보다 최종 병합된 규칙을 봐야 하는 이유입니다.

샌드박스를 켜면 OS 경계가 생깁니다

B의 Linux 도구 샌드박스는 운영체제 격리 도구를 사용합니다. 이 도구는 프로세스가 볼 파일과 네트워크 공간을 따로 만듭니다. 시스템 파일은 읽기 전용으로 보여주고, 쓰기가 필요한 작업공간만 별도로 열며, 네트워크 권한이 있을 때만 외부 연결 공간을 공유합니다.

.git은 작업공간이 쓰기 가능해도 다시 읽기 전용으로 덮습니다. .env.env.* 파일은 마스크 파일로 가립니다. 공개 구현에는 네트워크 설정, 읽기·쓰기 경로, 저장소 메타데이터와 비밀 파일 마스킹을 다루는 분기가 나뉘어 있습니다.

권한이 부족해 명령이 실패하면 샌드박스를 통째로 끄는 대신 확장 요청을 만들 수 있습니다.

특정 오픈소스 B의 샌드박스 확장 구조를 이해하기 쉽게 다시 썼습니다.

코드 예시실행 흐름
추가로 필요한 권한  network: true  file read: ~/.cache/package-manager  file write: ./generated사용자가 승인하면 이 실행에 추가 권한을 적용한다.

사용자는 “더 넓은 권한이 필요합니다”라는 추상적인 문장보다 어떤 경로와 네트워크가 필요한지 보고 판단할 수 있습니다. 권한을 작은 단위로 설명하는 승인 UI가 중요한 이유입니다.

하지만 도구 샌드박스는 코드상 기본 비활성입니다

정책 엔진이 있다고 해서 OS 격리가 자동으로 켜지는 것은 아닙니다. 분석한 코드에서 도구 샌드박스 설정의 기본값은 false입니다. 비활성 상태의 관리자는 환경을 정리한 뒤 원래 프로그램과 인자를 호스트에서 그대로 실행합니다.

.env 마스킹에도 범위가 있습니다. Linux 구현은 정해진 깊이까지만 파일을 찾고, 검색 중 오류가 나면 실행을 계속합니다. 샌드박스를 끈 상태에는 이 파일 마스킹도 경계가 되지 않습니다.

따라서 B의 설계는 “정책 엔진이 곧 샌드박스”라는 사례가 아닙니다. 오히려 승인 정책과 선택형 실행 격리를 별도 설정으로 운영하는 사례입니다.

5. 특정 오픈소스 C: 권한 UI는 격리가 아니라고 선을 긋습니다

특정 오픈소스 C의 권한 평가기는 규칙을 선언된 순서대로 합치고 마지막으로 일치한 규칙을 사용합니다. 맞는 규칙이 없으면 사용자에게 묻습니다. 사용자는 한 번 허용하거나, 현재 세션에서 비슷한 패턴을 계속 허용하거나, 거부할 수 있습니다.

기본 빌드 에이전트는 대부분의 행동을 허용합니다. 작업공간 밖 디렉터리와 반복 루프는 질문하고, 파일 읽기 도구로 .env 계열에 접근할 때도 묻습니다.

특정 오픈소스 C의 기본 규칙을 축약한 편집본입니다.

코드 예시JSON
{  "*": "allow",  "external_directory": "ask",  "read": {    "*": "allow",    "*.env": "ask",    "*.env.*": "ask"  }}

계획 에이전트는 편집을 거부하되 계획 파일은 허용합니다. 하지만 사용자 규칙이 내장 규칙 뒤에 병합되므로 설정 순서가 결과를 바꿀 수 있습니다.

하위 에이전트 경계도 주의해야 합니다. 회귀 테스트는 계획 에이전트가 편집을 막더라도, 자체 정책으로 편집을 허용한 하위 에이전트는 파일을 바꿀 수 있음을 확인합니다. 반대로 세션 수준에서 명시한 deny 규칙은 하위 에이전트에도 강제 상한으로 전달됩니다.

즉 “상위 에이전트가 계획 모드니까 모든 하위 작업도 읽기 전용”이라고 가정하면 안 됩니다. 위임할 때 어떤 권한을 상속하고 어떤 권한을 새로 계산하는지 확인해야 합니다.

이 프로젝트는 권한 시스템의 한계를 직접 밝힙니다

특정 오픈소스 C의 공식 보안 문서는 어떤 공격과 한계를 가정하는지 설명하면서, 에이전트를 샌드박스하지 않는다고 명시합니다. 권한 시스템은 사용자가 행동을 인지하고 확인하도록 돕는 UX이며, 보안 격리를 제공하도록 설계되지 않았다고 설명합니다. 실제 격리가 필요하면 컨테이너나 VM에서 실행하라고 권합니다.

이 구분은 정직하고 유용합니다. 외부 경로를 감지해 승인 창을 띄우는 코드와 테스트가 있어도, 셸 프로세스는 결국 현재 사용자의 파일·프로세스·네트워크 권한을 물려받습니다. 사용자가 승인하거나 감지하지 못한 경로가 있다면 OS가 마지막에 한 번 더 막아주지 않습니다.

출력 제한도 보안 경계와 구분해야 합니다. C는 셸 출력이 기본 줄 수나 바이트 수를 넘으면 모델에 보이는 내용을 줄입니다. 그러나 전체 출력은 임시 파일에 저장되고 일정 기간 뒤 정리됩니다. 이는 컨텍스트 크기를 다루는 기능이지 비밀정보를 마스킹하거나 즉시 삭제하는 기능은 아닙니다.

6. 세 구현에서 공통으로 보인 설계 원칙

세 프로젝트의 기본값은 서로 다르지만 공통으로 배울 수 있는 원칙이 있습니다.

첫째, 모드 이름보다 최종 능력을 확인해야 합니다. 읽기 전용이라는 이름 아래에서도 디스크 읽기 범위와 네트워크 상태는 다를 수 있습니다. 계획 모드에도 계획 파일 쓰기 예외가 있을 수 있습니다.

둘째, 승인 단위는 구체적이어야 합니다. “이 명령을 허용할까요?”보다 실행할 명령, 작업 경로, 추가 파일 경로, 네트워크 필요 여부를 함께 보여줘야 합니다.

셋째, 비대화형 실행은 별도 정책이 필요합니다. 사람이 없는 환경에서 질문을 무한 대기하거나 자동 허용으로 바꾸지 말고, 기본 거부와 좁은 허용 목록 중 하나를 명시해야 합니다.

넷째, 위임 경계를 테스트해야 합니다. 상위 에이전트의 제한이 하위 에이전트에 그대로 전달된다고 가정할 수 없습니다. 하위 에이전트가 자체 정책으로 다시 허용할 수 있는 권한과 세션 수준에서 강제 상한으로 전달되는 권한을 나눠 확인해야 합니다.

다섯째, 비밀정보는 파일·환경 변수·출력 보존을 함께 봐야 합니다. .env 파일 하나를 막는 규칙만으로 SSH 키, 클라우드 자격 증명, 명령 출력 속 토큰까지 보호할 수는 없습니다.

AGENTS.md가 “어떻게 작업할지” 알려주는 문서라면, 권한 정책은 “어디까지 실행할지” 정하는 장치입니다. 저장소 지침의 역할 분담은 스타 10만 오픈소스는 AGENTS.md를 어떻게 설계했을까에서 더 자세히 볼 수 있습니다.

그 경계 안에서 만든 변경을 어떤 증거로 검토하고 병합할지는 AI가 만든 PR, 테스트만 통과하면 병합해도 될까?에서 이어집니다.

7. 우리 팀 정책은 위험 명령 목록보다 능력으로 시작합니다

아래는 세 프로젝트의 원문이 아닙니다. 공개 구현에서 확인한 패턴을 팀 정책으로 옮긴 재구성 예시입니다.

코드 예시YAML 설정
# 개념 예시입니다. 특정 도구의 설정 파일이 아니므로 그대로 복사해 사용할 수 없습니다.default:  filesystem:    read:      - "./**"    deny_read:      - "./.env*"      - "~/.ssh/**"      - "~/.config/cloud/**"    write:      - "./**"    deny_write:      - "./.git/**"      - "./.agents/**"  network: deny  approval: on_requestallow_without_prompt:  - "git status"  - "git diff *"  - "pnpm test *"require_scoped_approval:  network:    show_domains: true  external_paths:    show_exact_paths: true  destructive_commands:    allow_persistent_rule: falseheadless:  default: deny  allowed_commands:    - "pnpm lint"    - "pnpm test"delegation:  child_permissions: intersect_with_parent

이 예시에서 핵심은 rm, sudo 같은 단어 목록이 아닙니다. 읽기·쓰기·네트워크·위임 능력을 먼저 제한하고, 자주 쓰는 안전한 명령만 좁게 자동 허용합니다.

pnpm test *도 무조건 안전하다고 단정할 수는 없습니다. 패키지 스크립트 자체가 네트워크 요청이나 파일 변경을 수행할 수 있기 때문입니다. 자동 허용 목록은 신뢰하는 저장소에서만 쓰고, 실행 능력은 샌드박스로 다시 제한해야 합니다.

팀 규칙을 만들 때는 다음 질문부터 답하면 좋습니다.

  1. 기본 읽기·쓰기 경로와 끝까지 보호할 메타데이터는 무엇인가?
  2. 네트워크와 외부 경로 승인은 어느 범위까지 열리는가?
  3. 비대화형 실행과 하위 에이전트에도 같은 상한이 적용되는가?
  4. 환경 변수와 전체 명령 출력은 어디에 얼마나 오래 남는가?

보안 검토 역시 추상적인 “안전해 보인다”보다 재현 가능한 실패를 찾아야 합니다. 코드 리뷰의 근거 기준과 중단 조건은 AI 프론트엔드 코드 리뷰 Skill: 결함을 행동 테스트로 연결하는 법의 접근을 그대로 적용할 수 있습니다.

8. 도입 순서는 작고 확인 가능하게

처음부터 완벽한 정책 엔진을 만들 필요는 없습니다.

먼저 현재 에이전트가 어떤 OS 사용자로 실행되고, 샌드박스가 실제로 활성화됐는지 확인합니다. 제품 설정 화면의 이름만 보지 말고 작업공간 밖 파일 쓰기와 네트워크 요청을 테스트 환경에서 직접 시도해 경계를 확인합니다.

그다음 작업공간 쓰기와 네트워크 차단을 기본으로 둡니다. 홈 디렉터리 전체 읽기가 필요하지 않다면 읽기 범위도 프로젝트로 줄입니다. .git, 에이전트 설정, 자격 증명 경로는 별도 거부 규칙으로 보호합니다.

세 번째로 승인 로그를 살펴봅니다. 사람들이 반복해서 기계적으로 승인하는 요청은 자동 허용 후보가 아니라, 샌드박스 범위를 조정하거나 명령을 더 작게 나눌 신호일 수 있습니다.

마지막으로 비대화형 실행과 하위 에이전트를 따로 검증합니다. 대화형 터미널에서 안전했던 정책이 CI, 원격 서버, 자동 위임에서도 같은 방식으로 동작한다고 가정하지 않습니다.

공개 저장소의 테스트는 구현 의도를 보여주지만, 우리 환경의 실제 보장을 대신하지는 않습니다. 운영체제, 컨테이너 마운트, 사용자 설정, 관리자 정책에 따라 최종 능력은 달라집니다.

9. 결론: 믿음이 아니라 겹친 경계로 맡깁니다

AI 에이전트에게 터미널을 맡길 수 있느냐는 질문에 예·아니오로 답하기는 어렵습니다. 더 좋은 질문은 “실수로 승인해도 피해가 어디에서 멈추는가”입니다.

특정 오픈소스 A는 작업공간 쓰기와 네트워크를 분리하고, 특정 오픈소스 B는 정책 엔진과 선택형 OS 샌드박스를 겹칩니다. 특정 오픈소스 C는 승인 UX가 보안 격리는 아니라는 한계를 분명히 밝힙니다.

세 사례를 함께 보면 실무 기준이 선명해집니다. 승인 창은 사람의 판단을 돕고, 샌드박스는 그 판단이 틀렸을 때 능력을 제한하며, 데이터 경계는 읽힌 정보와 출력이 흘러가는 길을 줄입니다.

터미널을 맡긴다는 것은 에이전트를 전적으로 믿는 일이 아닙니다. 사람과 모델이 모두 실수할 수 있다는 전제에서, 작은 권한과 분명한 탈출구, 마지막에 남는 강제 경계를 설계하는 일입니다.

분석한 오픈소스와 원문 출처

본문에서는 분석 대상을 특정 오픈소스 A·B·C라는 가명으로 표현했습니다. 아래에서만 실제 프로젝트명을 밝힙니다. 링크는 분석에 사용한 파일 상태를 가리키는 고정 주소입니다. 편집 발췌는 여러 코드와 테스트의 핵심을 축약·번역한 것이며 원문 그대로의 코드가 아닙니다.

이 글은 고정된 공개 파일의 설계와 테스트를 분석한 글이며 세 프로젝트의 공식 입장을 대신하지 않습니다. 테스트 정의는 구현 의도를 보여주지만 모든 배포에서 실행됐거나 필수였음을 증명하지 않습니다. 사용자의 실제 설정, 운영체제 경계, 관리자 정책, 저장소 밖의 사용 빈도와 보안 효과는 확인하지 않았습니다.

함께 읽을 글

관련 AI 개발 글

스타 10만 오픈소스는 AGENTS.md를 어떻게 설계했을까관련 글 읽기