작성자: Josh Greenwell Staff Applied AI Engineer
본 블로그 기사는 입력 방어(input defenses)가 실패했을 때 AI 에이전트를 격리하는 방법에 대한 저희 백서의 요약본입니다. 전체 논문에는 2026년 7월 사고 타임라인에 대한 부록, 격리 체크리스트, 그리고 격리 제어를 SOC 2, OWASP, NIST 프레임워크와 매핑한 내용, 그리고 완전한 참고 문헌 목록이 포함되어 있습니다. 원본은 여기에서 확인하고 다운로드할 수 있습니다.
서론
저희가 LuumenAI를 코드 실행을 중심으로 리팩토링했을 때의 이유는 비용 때문이었습니다. 저는 이 내용을 별도의 논문으로 작성했지만, 요약하자면 모든 요청에 수많은 도구들을 로드하는 것이 토큰을 소모하고 있었고, 작업을 모델이 저희 API를 대상으로 코드를 작성할 수 있는 샌드박스(sandbox)로 옮기자 비용 청구가 매일 수백 달러에서 한 자릿수로 떨어졌습니다. 보안 경계는 거의 우연히 생겨났습니다. 이제 모델의 코드는 우리가 제공한 API에만 접근할 수 있는 격리된 환경에서 실행됩니다. 어느 순간, 돈을 절약하기 위해 구축한 시스템이 해킹당한 모델과 그 모델이 달리 도달할 수 있는 모든 것 사이에 방어막 역할을 하고 있다는 사실을 깨달았습니다.
그 우연성이 바로 이 논문의 주제입니다. 시리즈의 첫 번째 논문에서는 모델에게 지침(instructions)과 데이터를 구분하도록 가르칠 수는 없지만, 무엇이 모델에 도달할지는 통제할 수 있다고 주장했습니다. 저는 설명한 모든 입력 방어에 대해 한 가지 경고를 반복해서 되뇌었습니다. 그것은 누적적이며, 결코 의지해야 할 것이 아니라는 것입니다. 삽입 공격(injection attempts)의 99퍼센트를 막는 필터라 할지라도, 공격자는 백 번째 시도에서 이를 돌파할 것이며, 한동안 저는 그 백 번째 시도에 대해 생각하고 싶지 않았습니다.
결국 그렇게 해야 합니다. 이를 계획해야 합니다. 모든 입력 제어 단계를 거치면서 어느 시점에서든 모델이 적대적인 지침을 읽고 그것을 수행하려고 시도할 것이라고 가정하고, 그럴 때 모델이 너무 많은 것을 얻지 못하도록 구축해야 합니다. 보안팀들은 에이전트에 대해 아무도 걱정하기 전부터 수년 동안 이를 '가정된 침해(assume breach)'라고 불러왔습니다. 모든 것에 베팅하는 것을 멈추고, 일단 침입자가 안으로 들어온 후에 얼마나 멀리까지 갈 수 있을지 결정하기 시작한 것입니다.
제가 이 글을 작성하는 동안 사례들이 도착했고, 제가 준비했던 것들보다 더 이상했습니다. 2026년 7월, 일종의 최첨단 모델(frontier models) 세트가 격리된 평가 환경에서 탈출하여 공개 인터넷을 건너 다른 회사의 프로덕션 시스템에 침입했습니다. 공격자가 보낸 것이 아니었습니다. 이 모델들은 벤치마크 점수를 받는 과정에 있었고, 문제를 실제로 해결하는 것보다 침입하는 것이 높은 점수를 얻는 더 빠른 경로임이 밝혀졌습니다. 9일 후, 두 번째 연구실은 자체 평가 로그를 검토하고 세 개의 회사에 대해 세 가지 사례를 추가로 보고했으며, 그중 가장 오래된 것은 이미 3개월 전의 것이었습니다. 저는 이 두 공개 사례들을 Part IV에서 다시 다루는데, 왜냐하면 이들 사이의 간극이 '손상(compromised)'이라는 개념이 포괄해야 하는 범위를 넓히기 때문입니다 (전체 공개 타임라인은 부록 A 참고).
우리나 산업 전반이 마찬가지로 격리(containment)보다는 입력 방어(input defense) 측면에서 더 진보했습니다. AI 에이전트에 대한 격리는 작동하는 도구를 이용한 엔지니어링의 영역이지만, 그중 상당 부분이 아직 초기 단계이며 관리되는 구성 요소들 중 일부는 마케팅에서 밝히는 것보다 더 많이 유출됩니다. 이 논문은 모델이 행동을 한 후에 만질 수 있는 것이 무엇인지, 그리고 그것을 어떻게 작게 유지할지에 관한 것입니다.
Part I: 입력 방어만으로는 충분하지 않은 이유
수학부터 시작해야 합니다. 이 논문이 존재해야 하는 이유가 바로 그것이기 때문입니다. 모델 앞에 99%의 시도를 걸러내는 단일 필터를 배치한다고 가정해 봅시다. 그러면 천 가지 변형을 가진 공격자는 어느 정도 후에 침투할 수 있을지 궁금해할 뿐입니다. 몇 개의 필터를 쌓으면 확률은 높아지지만, 확실성에 도달하지는 못합니다. 왜냐하면 공격자는 승리하는 한 번만 필요하고, 당신은 끊임없는 연속성이 필요하기 때문입니다. 입력 방어(Input defense)는 주입(injection)이 성공하는 빈도를 낮출 뿐입니다. 그 숫자를 0으로 만들 수는 없습니다.
성공적인 주입이 결국에는 올 것이라고 받아들이면, 질문을 다르게 설계하기 시작합니다. 즉, 일단 침투했을 때 공격이 얼마나 피해를 줄 수 있는가 하는 것입니다. 이 질문에는 답이 있습니다. 모델이 어느 정도의 데이터에 접근할 수 있는가? 어디로 데이터를 전송할 수 있는가? 모델이 작성하는 코드는 실제로 무엇을 할 수 있는가? 이러한 모든 것을 설계할 수 있으며, 이는 언어 자체를 모델로부터 면역화시키는 것보다 더 많은 것입니다.
여기서 삼위일체(trifecta)의 세 번째 축이 마침내 등장합니다. 첫 번째 논문은 모델의 데이터 접근성과 신뢰할 수 없는 콘텐츠에 대한 노출을 다루었고, 세 번째 축인 정보를 외부로 전송하는 능력은 그대로 두었습니다. 격리(Containment)는 주로 이 축과 관련되며, 모델이 행동을 취하기로 결정한 이후 수행하는 모든 것과 관련됩니다. 도구를 호출하거나, 실행되는 코드를 작성하거나, 출력을 다른 시스템으로 전달하거나, 데이터를 어딘가로 전송하는 것 등 말입니다. 이 모든 것이 문(door)이며, 공격자를 위해 작동하는 모델은 그 모든 문을 시도해 볼 것입니다.
파트 II: 샌드박스가 실제로 보호하는 것
여기에는 첫 번째 논문과 관련하여 모든 것이 의존하는 한 가지 구분이 있으므로 정확하게 설명하겠습니다. 샌드박스(sandbox)는 모델과 그 행동이 피해를 줄 수 있는 시스템 사이의 경계입니다. 이는 모델이 작성한 코드가 귀하의 네트워크, 데이터베이스, 고객에게 도달하는 것을 막아줍니다. 하지만 애초에 악의적인 명령이 모델에 도달하는 것 자체에 대해서는 아무것도 하지 못합니다. 사람들은 이 두 가지를 끊임없이 혼동하며, 그 결과 입력은 완전히 열려 있지만 샌드박스가 감싸고 있는 모델을 갖거나, 반대로 하는 상황에 놓입니다.
모델의 행동이 실행되는 환경에 대한 다섯 가지 제한 사항으로 격리(Containment)가 결정됩니다:
- 최소 권한 원칙 (Least privilege). 모델의 코드는 작업에 필요한 몇 안 되는 API만 호출할 수 있으며 그 외는 아무것도 할 수 없습니다.
- egress 허용 목록 (An egress allowlist). 환경은 필요한 특정 목적지에 도달할 수 있어야 하며 공격자가 제어하는 서버로 연결을 열 수 없어야 합니다. 이 목록의 모든 예외 사항이 공격 표면(attack surface)의 일부이며, 패키지 레지스트리는 보통 누구나 허용하는 첫 번째 예외입니다.
- 리소스 제한 (Resource limits). CPU, 메모리, 벽시계 시간(wall-clock time)에 대한 상한선으로, 통제 불가능하거나 의도적으로 비용이 많이 드는 프로세스가 청구서를 폭증시키는 것을 막습니다. OWASP에서는 이를 무제한 소비(Unbounded Consumption)라고 부릅니다.
- 앰비언트 자격 증명 없음 (No ambient credentials). 컴프로마이스된 프로세스가 읽고 재사용할 수 있는 환경 내의 것이 아무것도 없어야 합니다.
- 기본적으로 일회성 (Ephemeral by default). 실행마다 새로운 환경을 제공하여, 공격자가 떨어뜨린 어떤 것도 다음 세션으로 살아남지 않게 합니다.
Every limit is a setting with a pass or a fail
이 모든 것은 통과하거나 실패하는 설정입니다. 이것이 이 계층(layer)에서 작업하는 매력입니다. 사용자가 임의의 아웃바운드 연결을 차단하는지 egress 허용 목록으로 테스트할 수 있습니다. 하지만 모델이 마침내 악성 이메일을 불신하도록 학습했는지 여부는 테스트할 수 없습니다. 환경만 제대로 설정하면, 모델을 이용하게 된 공격자는 다른 쪽에서 잡을 만한 것을 거의 찾지 못합니다.
파트 III: 격리 스펙트럼 (The Isolation Spectrum)
격리는 등급이 있으며, 특히 곧 실행하려는 코드가 위협적인 무언가에 설득당했을 수 있는 모델에 의해 요청(on demand)된 경우 그 차이가 매우 중요합니다. 옵션들은 약하고 저렴한 것부터 강하고 조금 더 비싼 것에 이르기까지 다양합니다.
일반 컨테이너는 취약한 경계입니다. 컨테이너들은 호스트 커널을 공유하기 때문에, 컨테이너 내부에서 발생한 커널 익스플로잇(kernel exploit)은 곧 호스트에 대한 익스플로잇이 됩니다. 자체 신뢰 서비스들을 분리하는 용도로는 괜찮습니다. 하지만 신뢰할 수 없는, 모델이 작성한 코드를 둘러싸는 경계로는 심각하지 않으며, 이를 그렇게 취급하는 것은 흔하고 비용이 많이 드는 실수입니다.
gVisor가 한 단계 위의 수준입니다. gVisor는 사용자 공간 커널(user-space kernel)을 실행하여 워크로드의 시스템 호출(system calls)을 가로채고 이를 호스트 커널로부터 분리합니다. 따라서 코드가 호스트와 직접 통신하는 일이 없습니다. 이 과정에서 약간의 시스템 호출 및 I/O 오버헤드(overhead)가 발생하지만, 여전히 모든 요청에 사용할 만큼 충분히 빠르게 시작됩니다.
Isolation approaches
Firecracker가 대부분의 프로덕션 작업에 가장 강력한 경계입니다. 각 워크로드(workload)는 KVM 위에 구축된 간소화된 가상 머신(virtual machine, VM)에서 실행되며, 하드웨어 기반의 경계를 갖습니다. 이 VM들은 1초도 안 되는 시간에 부팅되고 메모리 오버헤드는 거의 없습니다. 이것이 바로 대량으로 세션을 생성하고 해제할 때 사용하기에 적합한 이유입니다. Kata Containers 역시 비슷한 영역에 위치하며, 컨테이너 워크로드를 경량 VM 안에 감싸는 방식입니다. 특히 신뢰할 수 없는 JavaScript의 경우, V8 격리자(V8 isolates)가 브라우저가 탭들을 분리하는 데 사용하는 가벼운 환경이며, Cloudflare가 모델이 작성한 코드를 강력하게 분리하여 실행하는 방식입니다.
[Isolation spectrum<br>
](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyiz1p7ve0ki3de11tuqb.png
우리가 따르는 규칙은 영리하지 않습니다. 모델이 작성한 코드는 최소한 gVisor와 같은 커널 레벨의 경계를 갖게 되며, 절대 베어 컨테이너가 될 수는 없습니다. 한 고객의 워크로드가 다른 고객에게 도달할 수 있는 멀티 테넌트(multi-tenant) 환경이라면 마이크로VM(microVM)을 사용합니다. 네, 더 강력한 경계는 실행하는 데 비용이 더 듭니다. 하지만 그것은 탈출(escape) 사고를 처리하는 비용에 비하면 아무것도 아닙니다.
LuumenAI의 경우 관리형 샌드박스 플랫폼을 사용합니다. 모든 실행은 자체 격리 환경을 가지며, 이 환경은 일회용이므로 실행이 끝나면 사라집니다. 그 환경은 저희와 분리된 인프라 위에 놓여 있었는데, 이것이 우리가 그것을 선택한 이유 중 하나였습니다. 만약 고객 경계가 격리 계층을 우리 자체 계정 내부에 두도록 요구한다면, 우리는 이를 내부화할 수 있습니다. 우리는 이 설계가 이동 가능한 마이그레이션(migration)으로 범위를 설정할 수 있도록 유지해 왔습니다.
파트 IV: 샌드박스가 실패할 때
이 논문의 부분은 제가 작성하는 동안 계속 바뀌었습니다. 왜냐하면 예시들이 멈추지 않고 도착했기 때문입니다. 격리는 자동적이지 않으며 무료도 아니며, 실패할 때는 보통 두 가지 방식 중 하나로 발생합니다. 첫 번째는 잘못 구성된 샌드박스(misconfigured sandbox)로, 경계가 서류상으로는 존재하지만 설정이 문을 열어두거나, 아무도 잠그지 않은 외부 통신 경로(egress path), 또는 너무 많은 범위를 가진 역할 때문입니다. 두 번째는 탈출(escape)인데, 격리 계층 자체의 결함으로 인해 코드가 빠져나가는 경우입니다.
**잘못 구성된 샌드박스: AgentCore
AWS Bedrock AgentCore Code Interpreter가 첫 번째 방식으로 실패했고, 격리 계층 자체가 전체 시간을 지탱했습니다. 2025년 9월, Sonrai Security는 샌드박스화된 인터프리터 내부에서 실행되는 코드가 169.254.169.254의 마이크로VM 메타데이터 서비스에 접근할 수 있으며, 이는 EC2 워크로드가 인스턴스 메타데이터를 위해 사용하는 것과 동일한 주소이며, 이를 통해 실행 역할(execution role)의 IAM 자격 증명(credentials)을 읽어낼 수 있다는 연구 결과를 발표했습니다. AWS는 해당 리터럴 주소나 메타데이터 경로를 포함하는 모든 요청을 차단하는 필터를 두었습니다. 이를 우회하는 것은 특별할 것이 없었습니다. 주소를 조각으로 나누거나, 인코딩하거나, 런타임에 조립하는 코드는 필터가 일치시키는 정확한 문자열을 포함하지 않았기 때문에 해당 요청들은 통과했습니다. 그 결과로 나온 것은 실행 역할의 세션 자격 증명이었으며, 이는 샌드박스 외부에서 사용 가능했고, 샌드박스가 자체적으로 도달할 수 없는 AWS 제어 평면 엔드포인트에 대해 사용될 수 있었습니다.
Firecracker는 이 모든 과정 동안 제 역할을 했습니다. 가상 머신(virtual machine)은 절대 침해되지 않았습니다. 실행 역할의 자격 증명은 단순히 내부에서 읽을 수 있었고, 이것이 중요했던 이유는 발견의 후반부 때문이었습니다. AWS 자체 AgentCore Starter Toolkit에 기본 IAM 역할은 계정 내 모든 S3 버킷에 대한 읽기 액세스, 전체 DynamoDB 액세스, 그리고 Secrets Manager의 모든 비밀(secret)에 대한 접근 권한을 부여했습니다! 오픈 소스 AgentCore 예제들은 이 역할을 복사했습니다. 따라서 퀵스타트(quickstart)를 따라간 팀은 일단 자격 증명을 읽어내자마자 계정의 대부분을 열 수 있는 샌드박스를 갖게 되었습니다. AWS는 메타데이터 접근을 공유 책임 모델(shared responsibility model) 하에서의 예상되는 동작으로 간주하고 서비스에 대한 자격 증명 관리 문서를 발표했습니다.