-
샌드박스 정책에 반드시 들어가는 세 줄 — 그리고 각 줄이 막는 공격IT 2026. 8. 7. 22:30
샌드박스를 "켰다"는 말은 안심을 준다. 컨테이너를 띄우고 정책 파일을 하나 얹으면 뭔가 방어를 한 느낌이 든다. 그런데 앞선 글들에서 봤듯, 같은 "켰다"도 담을 어디에 긋고 무엇을 정책에 적었는지에 따라 막는 공격이 완전히 달라진다. 그래서 이번엔 반대로 물어본다 — 샌드박스 정책에 최소한 무엇이 적혀 있어야 "켰다"고 말할 수 있나?
NVIDIA가 에이전트 샌드박싱 가이드에서 이 질문에 못을 박았다. OS 수준에서 강제해야 할 필수 통제 세 가지를 제시했는데, 흥미로운 건 이 셋이 각각 서로 다른 공격 클래스 — 데이터 유출, 지속성 심기, 설정 변조 — 에 거의 1:1로 대응한다는 점이다. 세 줄을 하나씩 그 공격에 붙여보자. 그리고 마지막에, 이 세 줄을 다 채워도 여전히 정문으로 걸어 나가는 한 부류의 공격이 남는다는 것까지 본다.
세 통제와 각자 막는 공격
다이어그램 설명. 샌드박스 정책이 반드시 담아야 할 세 통제와, 각 통제가 봉쇄하는 공격을 짝지어 보여준다. "네트워크 egress 통제"는 임의 사이트로 나가는 길을 막아 데이터 유출과 원격 조종(리버스셸)을 끊는다. "workspace 밖 파일 write 차단"은 작업 폴더 바깥에 파일을 심는 걸 막아 악성 코드가 시스템에 상주하거나 담을 넘거나 원격 코드 실행으로 번지는 걸 차단한다. "config 파일 write 차단"은 설정 파일 수정을 막아 훅·스킬·MCP 설정 변조를 봉쇄한다. 세 통제가 서로 다른 공격 표면을 하나씩 덮는다는 게 핵심이다 — 하나라도 빠지면 그 열이 통째로 열린다. 아래에서 특히 세 번째를 자세히 본다.
① egress 통제 — 훔쳐도 가져갈 길을 끊는다
egress(나가는 네트워크 트래픽) 통제는 허용목록에 없는 목적지로의 접속을 차단한다. 지난 시리즈에서 본 tool poisoning — 도구 설명문에 "이 파일을 읽어 여기로 보내라"는 숨은 지시를 심는 공격 — 이 이 통제에서 잘 잘린다. 산수 도구가 낯선 외부 도메인으로 아웃바운드를 칠 이유가 없으므로, "그 도구가 쓸 일 없는 목적지는 전부 막는다"는 정책이 기능을 하나도 해치지 않으면서 유출 채널만 자른다. 유출을 훔치는 데 성공해도 가지고 나갈 길이 없으면 공격은 미완이다.
② workspace 밖 write 차단 — 흔적을 못 남기게 한다
두 번째는 작업 디렉터리 바깥에 파일을 쓰지 못하게 막는다. 왜 write가 그렇게 위험한가? 시스템에 오래 살아남는 공격은 대개 어딘가에 파일을 남긴다 — 로그인 시 자동 실행되는 스크립트, 셸 설정 파일에 끼워넣은 한 줄, 크론 작업 같은 흔적이다. 작업 폴더 밖 write를 막으면 이런 지속성(persistence) 심기, 샌드박스 탈출, 원격 코드 실행 기법이 한꺼번에 봉쇄된다. 실제 구현에서는
~/.ssh·/etc같은 민감 경로 마운트를 심링크까지 따라가며 검증해 거부하는 식으로 나타난다 — 우회 경로를 심링크로 뚫으려는 시도까지 fail-closed(막힐 땐 여는 게 아니라 닫는 원칙)로 잠근다.③ config write 차단 — 설정에 자기를 심는 지속성을 끊는다
여기가 이번 글의 집중 꼭지다. 세 번째 통제는 설정 파일에 대한 쓰기를 막는다. 언뜻 밋밋해 보이는데, 이게 지속성(persistence) 심기 — 샌드박스 안에서 도는 악성 코드가 자기를 다음 세션에도 계속 로딩되게 설정에 등록해두는 수법 — 을 정면으로 끊는다.
지속성이 무서운 건 한 번 심어두면 계속 남는다는 점이다. 샌드박스 안의 악성 코드가 MCP 설정 파일을 조용히 고쳐 자기를 상시 로딩되게 등록하거나, 에이전트의 훅·스킬 정의를 바꿔 매 실행마다 자기 코드를 끼워넣으면, 사용자가 눈치채기 전까지 반복해서 작동한다 — 게다가 훅·스킬·MCP 설정은 흔히 샌드박스 바깥 권한으로 실행되므로, 이 심어놓기는 곧 샌드박스 탈출의 발판이기도 하다. config write 차단은 이 "심어놓기"를 막는다. 설정을 못 고치면 이번 한 번의 악성 행위로 끝나지, 다음 세션까지 이어지지 못한다.
여기서 한 가지가 헷갈리기 쉽다 — ②(작업 폴더 밖 write 차단)가 이미 있는데 ③가 왜 따로 필요한가? 둘은 겹치는 듯 보이지만 사정거리가 다르다. ②의 논리는 "작업 폴더 안은 네 공간이니 자유롭게 써라, 대신 밖으로는 못 나간다"이므로, workspace 안은 원칙적으로 쓰기 허용 구역이다. 문제는 MCP 설정 파일이나 훅·스킬 정의가 작업 폴더 안에 놓여 있을 때다 — 프로젝트 로컬
.mcp.json,.cursorrules,CLAUDE.md같은 파일들. 이건 작업 폴더 안이라 ②가 "정상 작업"으로 통과시켜 버린다. 그래서 ③는 위치를 불문하고 config 파일만 콕 집어 다시 잠근다 — "작업 폴더 안이라도, 그게 config면 에이전트가 스스로 고치는 건 안 된다." NVIDIA 가이드가 "설정 파일은 어디에 있든 쓰기를 막고, IDE의 승인조차 불가능하게 하라"고 못 박은 이유가 여기 있다. 같은 파일 쓰기라도 일반 소스는 이번 세션 한정의 행위지만, config는 다음 세션·매 실행마다 로딩될 설정을 바꿔 지속성을 심는 행위라 파급이 미래로 번진다. ③의 존재 이유는 바로 ②가 통과시키는 이 사각지대 — 작업 폴더 안의 config — 를 메우는 데 있다.다이어그램 설명. 샌드박스 안 악성 코드가 오래 남기 위해 노리는 두 지점 — MCP 설정 파일과 훅·스킬 정의 — 을 보여주고, config write 차단이 그 둘을 모두 막는 위치를 짚는다. 두 경로 다 "설정을 고쳐 지속성을 확보"하려는 시도이므로, 설정 쓰기를 잠그면 한 통제로 둘 다 봉쇄된다. 다만 마지막 노드가 이 통제의 한계를 분명히 한다 — config write 차단은 설정을 고쳐 새 발판을 심는 것을 막을 뿐, 이미 실행 권한을 얻은 코드가 자기에게 허락된 정상 통로로 하는 행동은 보지 못한다. 설정을 한 줄도 건드리지 않고 정상 API 호출의 필드 하나만 오염시키는 공격이라면 이 통제의 사정거리 밖이다 — 그 부류는 아래에서 세 통제의 공통 약점으로 다시 만난다.
세 통제의 공통 약점 — 행동은 보고, 내용은 못 본다
세 통제를 나란히 놓으면 공통점이 드러난다. 셋 다 프로세스가 무엇을 하려는가(어디로 접속·어디에 쓰기)를 막지, 무엇이 실려 있는가(요청 본문에 담긴 내용)를 보지 않는다. 그래서 유출이 "허용된 목적지로, 정상적인 쓰기 없이, 설정 변경 없이" 이뤄지면 세 통제 모두 아래로 지나간다.
NVIDIA 가이드 자신이 이 한계를 인정한다. "공격자는 흔히 indirection을 쓴다 — 더 안전한, 승인된 도구를 통해 더 제한된 도구를 호출하는 방식으로 애플리케이션 수준 통제를 우회한다." 이들의 답은 이 세 통제를 애플리케이션이 아니라 OS 수준에서 강제하는 것이다. 그런데 그 OS 수준 egress조차, 신뢰 도구의 정상 통로가 곧 유출 목적지일 때는 무력하다. config를 고치지도(③ 통과), 작업 폴더 밖에 쓰지도(② 통과), 낯선 목적지로 나가지도(① 통과) 않으면서 유출을 완성하는 공격이 있기 때문이다. 그 정확한 실패 지점 — 그리고 왜 담을 어디에 긋든 그 공격이 통과하는지 — 는 다음 글에서 따로 파고든다.
정리 — 정책을 볼 때 세 줄부터 확인한다
누군가 "샌드박스 정책을 적용했다"고 하면, 이제 나는 그 정책 파일에서 세 줄부터 찾는다 — 나가는 네트워크를 잠갔나, 작업 폴더 밖 쓰기를 막았나, 설정 파일 수정을 봉쇄했나. 이 셋이 없으면 그건 켠 시늉일 뿐이다. 세 줄이 각각 유출·지속성·변조라는 서로 다른 공격을 덮기 때문에, 하나라도 비면 그 방향이 통째로 열린다.
다만 세 줄을 다 채워도 남는 게 있다는 걸 잊지 않는 게 중요하다. 세 통제는 모두 "행동"을 막고 "내용"을 못 본다. 정문으로 걸어 나가는 유출은 이 세 줄 아래를 지나간다 — 그래서 정책 세 줄은 방어의 끝이 아니라 시작이다.
참고한 공개 자료:
- Practical Security Guidance for Sandboxing Agentic Workflows and Managing Execution Risk — NVIDIA Technical Blog (https://developer.nvidia.com/blog/practical-security-guidance-for-sandboxing-agentic-workflows-and-managing-execution-risk/)
- OpenShell: The safe, private runtime for autonomous AI agents — NVIDIA (https://github.com/NVIDIA/OpenShell)
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
MCP를 전부 컨테이너에 가뒀다, 딱 하나만 빼고 — 샌드박스 담에 문을 내는 법과 그 대가 (0) 2026.08.07 130개의 보안 경고를 가진 에이전트를 집에서 안전하게 돌리는 법 — OpenShell로 케이지에 넣기 (0) 2026.08.07 에이전트를 샌드박싱한다 — 그 한 문장이 숨기는 세 개의 경계 (0) 2026.08.07 cherry-pick과 revert — 브랜치 전체가 아니라 커밋 하나만 다루고 싶을 때 (0) 2026.08.06 충돌은 왜 rebase에서 더 자주 만날까 — merge는 한 번, rebase는 커밋마다 (0) 2026.08.06 rebase가 위험하다는 말의 진짜 의미 — 커밋은 이동하지 않고 복제된다 (0) 2026.08.06 fast-forward의 정체 — 어떤 날은 merge commit이 생기고 어떤 날은 안 생기는 이유 (0) 2026.08.06 브랜치를 합치는 세 가지 방법 — merge, rebase, squash는 히스토리 모양이 다르다 (0) 2026.08.06 생성은 값싸졌지만 검증은 아니다 — AI 코딩의 새로운 병목 (0) 2026.08.05 스펙이 새로운 소스코드다? — 가장 뜨거운 주장의 팽팽한 뒷면 (0) 2026.08.05