로컬 에이전트를 위한 보안 샌드박스 구현

코딩 에이전트는 환경을 탐색하고 변경하기 위해 터미널 명령을 실행하는 데 점점 더 능숙해지고 있습니다. 이러한 명령을 자동 승인하는 사용자는 훨씬 더 강력한 에이전트를 활용할 수 있지만, 그만큼 위험도 커집니다. 실수한 에이전트는 데이터베이스를 삭제하거나, 깨진 코드를 배포하거나, 시크릿을 유출할 수 있습니다.
모든 명령에 사람의 승인을 요구하면 이런 위험을 줄일 수 있지만, 대개는 일시적일 뿐입니다. 승인 요청이 쌓일수록 사용자는 이를 꼼꼼히 살펴보지 않게 됩니다. 여러 에이전트를 병렬로 실행하고 승인 프롬프트 간에 컨텍스트를 전환해야 할 때는 상황이 더 악화됩니다. 그 결과 승인 피로가 생기고, 이는 애초에 승인 절차를 둔 목적을 약화시킵니다.
지난 3개월 동안 우리는 macOS, Linux, Windows에서 에이전트 샌드박싱을 도입해 이 문제를 해결해 왔습니다. 샌드박스된 에이전트는 제어된 환경 안에서는 자유롭게 실행되며, 그 밖으로 나가야 할 때(대부분 인터넷에 접근할 때)만 승인을 요청합니다.
이를 통해 중단이 크게 줄어듭니다. 샌드박스된 에이전트는 샌드박스되지 않은 에이전트보다 멈추는 빈도가 40% 낮아, 사용자의 수동 검토 및 승인에 드는 시간을 크게 절약해 줍니다.


우리의 샌드박스 목표
우리는 보안을 강화하면서도 작업 중단을 없애겠다는 목표로 샌드박싱 작업을 시작했습니다. Agent가 효과적으로 작업할 수 있을 만큼의 자유는 주되, 위험을 초래하는 권한은 허용하지 않으려 했습니다.
이 균형을 맞추는 일은 보기보다 어렵습니다. 많은 터미널 명령은 기본적인 테스트나 빌드 단계조차도 예상치 못한 권한을 요구합니다. 단순한 샌드박스는 이런 것들을 차단해 버려 Agent의 워크플로를 깨뜨릴 수 있습니다. 실사용 가능한 샌드박스를 설계하는 일은, 각 운영 체제가 설정한 제약 내에서 보안과 사용성 간의 절충을 정교하게 설계하는 과정입니다.
구현
우리는 각 플랫폼마다 구현 방식은 다르지만, 동일한 샌드박스 API를 제공합니다. macOS, Linux, 그리고 Windows는 서로 다른 샌드박싱 기본 메커니즘을 제공하며, 이는 기저 설계 결정에 영향을 미쳤습니다.
macOS
우리는 macOS에서 네 가지 샌드박싱 방식을 평가했습니다: App Sandbox, 컨테이너, 가상 머신, 그리고 Seatbelt. App Sandbox는 Mac App Store를 위해 설계된 기능으로, 에이전트가 실행할 수 있는 모든 바이너리에 Cursor가 서명해야 합니다. 이는 상당한 복잡성을 더할 뿐 아니라, 에이전트가 생성하거나 수정한 바이너리가 Cursor의 신뢰를 상속받게 되어 새로운 공격 벡터를 열어 줄 수 있습니다. 컨테이너를 사용하면 Linux 바이너리로만 제한되고, 가상 머신은 받아들이기 어려운 수준의 시작 지연과 메모리 오버헤드를 초래합니다.
그 결과 남은 옵션은 sandbox-exec를 통해 접근하는 Seatbelt였습니다. Seatbelt는 2007년에 도입되어 2016년에 더 이상 사용이 권장되지 않는(deprecated) 상태가 되었지만, 여전히 Chrome과 같은 핵심 서드 파티 애플리케이션에서 사용되고 있습니다. 이를 사용하면 전체 하위 프로세스 트리의 동작을 제약하는 샌드박스 프로파일 아래에서 명령을 실행할 수 있습니다.
프로파일은 고도로 세분화된 권한을 정의하며, 특이한 정책 언어를 통해 특정 파일 및 디렉터리에 대한 시스템 콜(syscall)과 읽기·쓰기 작업을 제한합니다. 우리는 워크스페이스 수준 및 관리자 수준 설정, 그리고 사용자의 .cursorignore를 기반으로 이 정책을 런타임에 동적으로 생성합니다.
(deny file-write* (regex "^.*\/\\\.vscode($|\/.*)")
)
(deny file-write* (require-all
(regex "^.*\/\\\.cursor($|\/.*)")
(require-not (regex "^.*\/\\\.cursor/(rules|commands|worktrees|skills|agents)($|\/.*)")))
)
(deny file-write* (regex "^.*\\\.code-workspace$"))
(deny file-write* (regex "^.*\/\\\.cursorignore$"))
(deny file-write* (regex "^.*\/\\\.git/config$"))
(deny file-write* (regex "^.*\/\\\.git/hooks($|\/.*)")
)
(deny file-write* (regex "^(/private)?/var/folders/.*-cursor(-[a-z]+)?-zsh($|\/.*)")
)
Linux
Linux는 macOS보다 쉽기도 하고 어렵기도 합니다. 커널은 Landlock과 seccomp을(를) 통해 필요한 프리미티브를 제공하지만, 이를 조합해 실제로 쓸만한 샌드박스를 만드는 책임은 유저 공간(user space)에 있습니다. 여러 오픈 소스 프로젝트가 이러한 메커니즘을 효과적으로 결합하고 있지만, .cursorignore 같은 기능을 지원하는 프로젝트는 없습니다.
우리는 Landlock과 seccomp를 직접 사용하기로 했습니다. Seccomp는 안전하지 않은 시스템 호출을 차단하고, Landlock은 파일 시스템 제한을 적용하여 .cursorignore로 무시된 파일을 샌드박스된 프로세스에서 완전히 접근 불가능하게 만들 수 있게 해줍니다. 우리는 사용자 워크스페이스를 오버레이 파일 시스템(overlay filesystem)에 매핑한 뒤, 무시된 파일을 읽거나 수정할 수 없는 Landlock 적용 사본으로 덮어씁니다.
이 파일들을 찾고 재마운트하는 작업이 Linux 샌드박싱에서 가장 느린 부분입니다. macOS가 하는 것처럼 파일 시스템 연산을 지연 방식으로 필터링할 수 있다면 더 쉬웠겠지만, Linux는 seccomp-bpf 컨텍스트에서 파일 경로에 쉽게 접근할 수 있는 방법을 제공하지 않습니다.
Windows
Windows에서는 Linux 샌드박스를 WSL2 안에서 실행합니다. 이와 동등한 네이티브 Windows용 샌드박스를 구현하는 것은 훨씬 더 어렵습니다. 기존의 대부분 샌드박싱 저수준 기능이 브라우저에 맞춰 설계되어 있어 범용 개발 도구를 지원하지 않기 때문입니다. 저희는 필요한 이러한 기능들이 제공될 수 있도록 Microsoft와 협력하고 있습니다.
에이전트에게 sandbox 사용법 가르치기
sandbox는 에이전트가 어떤 명령어가 sandbox 내부에서 성공할지 예측하고, 언제 권한 상승이 필요한지 인지할 수 있을 때에만 효과적입니다. 모델이 sandbox를 인지하도록 만들기 위해서는 에이전트 하네스에 변경이 필요했습니다.
우리는 먼저 Shell 도구 설명을 업데이트해 sandbox 제약 조건을 설명했습니다. 사용자 설정에 따라 명령어가 파일 시스템, Git, 네트워크에 대한 접근 권한을 가지고 실행되는지, 그리고 필요할 때 에이전트가 어떻게 더 높은 권한을 요청할 수 있는지를 명시했습니다. 만족스러운 기준선 수준의 하네스 변경을 얻기까지, 몇 가지 일반적인 롤아웃을 실행해 보고, 예상과 다르게 동작하는 부분을 찾아서 프롬프트를 수정한 뒤, 롤아웃을 다시 실행하는 식의 많은 수동 테스트가 필요했습니다.
그 다음, 내부 벤치마크인 Cursor Bench를 사용해 sandbox가 켜진 에이전트와 꺼진 에이전트를 비교하여 이러한 변경의 영향을 평가했습니다. 곧 공통적인 실패 양상을 발견했는데, 에이전트가 권한을 바꾸지 않은 채 동일한 터미널 명령어를 계속해서 재시도하는 것이었습니다.
이를 해결하기 위해 Shell 도구 결과를 렌더링하는 방식을 업데이트하여, 실패를 야기한 sandbox 제약을 명시적으로 드러내고, 특정 경우에는 에이전트가 권한을 상향(escalate)하라고 권장하도록 했습니다. 이러한 알림을 배포한 이후, 에이전트는 sandbox 관련 실패에서 훨씬 더 매끄럽게 복구할 수 있었고, 오프라인 평가 성능도 크게 향상되었습니다.
다만 오프라인 평가는 전체 그림의 일부만 보여 줄 뿐입니다. sandbox가 사용자 경험을 떨어뜨리지 않는다는 확신을 더 얻기 위해, 우리는 프로덕션 환경에서 sandbox를 천천히 롤아웃했습니다. 내부 및 외부에서 받은 피드백 덕분에 이 기능을 정식으로 배포할 수 있다는 확신을 얻었습니다. 이제 지원되는 플랫폼에서 들어오는 요청의 3분의 1이 sandbox 환경에서 실행되고 있으며, NVIDIA와 같은 많은 Enterprise 고객을 온보딩했습니다.
에이전트가 단순히 코드를 생성하는 수준을 넘어 실제 프로덕션 시스템을 운영하는 단계로 넘어가면서, 실행 경계를 마련하는 것은 무엇보다 중요합니다. 지금의 구현은 그 방향을 향한 한 걸음입니다. 앞으로는 환경의 제약 조건을 학습한 sandbox 네이티브 에이전트에 특히 기대하고 있습니다. 이런 에이전트는 도구 호출에만 제한되지 않고, 직접 스크립트와 프로그램을 작성할 자유를 부여받을 수 있습니다.
코딩의 미래와 관련된 깊이 있는 기술적 문제를 함께 풀어 보고 싶다면 hiring@cursor.com으로 연락해 주세요.