Back to all posts

키는 브로커가 쥡니다. 여러분의 AI 에이전트가 아니라.

A small robot stands at a polished broker counter; behind a metal grille, tagged keys (Slack, GitHub, Notion, Gmail) hang on hooks. The robot passes a paper slip through the window in a calm, polite transaction.

AI 에이전트 보안은 하나의 규칙에서 시작됩니다. 여러분의 AI 에이전트는 결코 여러분의 자격 증명을 쥐고 있어서는 안 됩니다. 이를 강제하는 38년 된 브로커 패턴을 소개합니다.

AI 에이전트는 혼란에 빠진 대리인(confused deputy)입니다. 이는 38년 된 보안 패턴이며, 그 해답 또한 그만큼 오래되었습니다. 에이전트와 그것이 호출해야 하는 SaaS API 사이에 브로커를 두는 것입니다. 신뢰할 수 있고, 관찰 가능하며, 결정론적이고, 감사 가능하며, 위조 불가능하고, 범위가 좁혀졌으며, 정책 기반인, 그리고 AI가 아닌 이 중간 계층이 여러분의 에이전트가 가져서는 안 될 자격 증명을 대신 쥐고 있습니다.

1988년, Norm Hardy는 그가 Tymshare에 있던 시절의 실제 사건을 설명하는 짧은 논문을 발표했습니다. FORT라는 Fortran 컴파일러가 SYSX라는 시스템 디렉터리에 있었습니다. 사용 통계를 수집하기 위해 컴파일러는 (SYSX)STAT에 쓰기를 해야 했고, 그래서 운영체제는 FORT에 SYSX 안의 어떤 파일이든 쓸 수 있도록 허가하는 "홈 파일 라이선스"를 부여했습니다. 시스템의 과금 파일 (SYSX)BILL도 그곳에 있었습니다. 컴파일러를 호출하는 사용자는 선택적 디버그 출력을 받을 파일 이름을 지정할 수 있었습니다. 어느 날 한 사용자가 (SYSX)BILL을 지정했습니다. 컴파일러는 OS에 그 파일을 쓰기용으로 열어 달라고 요청했고, OS는 홈 파일 라이선스를 보고 이를 허용했습니다. 과금 데이터는 덮어쓰였습니다. 컴파일러는 설계된 그대로 동작했을 뿐입니다. 결함은 아키텍처에 있었습니다.

Hardy는 이를 **혼란에 빠진 대리인 문제(confused deputy problem)**라고 명명했습니다. 권한을 가진 프로그램(대리인)이 자체적인 권한을 보유하고 있고, 권한이 더 낮은 호출자가 그에게 무언가를 해 달라고 요청하면, 대리인은 누구의 권한으로 행동하는지 혼란에 빠져 자신의 권한을 사용합니다. 해법은 그 권한을 대리인에게서 완전히 떼어 내어, 요청 시점에 호출을 중개하는 별도의 계층 뒤에 두는 것입니다. 그 계층이 바로 브로커입니다.

38년이 지난 지금, 여러분의 회사가 운영하는 모든 AI 에이전트는 혼란에 빠진 대리인입니다. 그리고 그중 대부분은 브로커 없이 돌아가고 있습니다.

AI 에이전트가 보안 문제를 더 악화시키는 이유

Hardy의 FORT는 입력 채널이 하나뿐이었습니다. 바로 커맨드 라인이죠. 현대의 AI 에이전트는 수십 개의 입력 채널을 가지고 있습니다. 이메일 본문, 가져온 웹페이지, 업로드된 PDF, MCP 서버의 도구 출력, 멀티 에이전트 시스템에서 동료 에이전트가 보낸 메시지 등. 컨텍스트 윈도에 들어오는 모든 것이 명령을 내릴 수 있으며, 설계상 에이전트는 그 모두를 정당한 것으로 취급합니다.

이는 전통적인 접근 제어가 의존하는 한 가지 전제를 무너뜨립니다. 바로 호출자가 입력을 통제한다는 전제입니다. 웹 앱에서는 호출자(인증된 세션)와 입력(HTTP 요청 본문)이 같은 곳에서 옵니다. 에이전트에게는 프롬프트를 구성하는 사람이 곧 호출자이며, 이는 이메일을 쓰거나 검색 결과를 심을 수 있는 공격자 역시 호출자라는 뜻입니다.

2025년 11월, PromptArmor의 보안 연구자들은 그것이 실제 운영 환경에서 어떻게 나타나는지 보여 주었습니다. 그들은 통합 가이드에 1픽셀 폰트로 악성 명령을 숨겼습니다. 한 개발자가 Google의 Antigravity IDE를 그 가이드로 향하게 하자, 에이전트는 cat을 셸로 호출하여 자신의 .gitignore 기반 파일 보호를 우회했습니다. 그런 다음 Antigravity 자체의 브라우저 서브에이전트를 통해 .env 파일의 내용을 공격자가 통제하는 webhook.site URL로 유출했습니다. 사용자는 모든 것을 올바르게 설정해 두었습니다. 샌드박스도 유지되었습니다. 에이전트는 단지 사용자가 요청한 것과 입력이 시키는 것을 구분하지 못했을 뿐입니다.

수십 년 뒤에 나타난, Hardy의 FORT와 똑같은 형태입니다. 광범위한 권한, 신뢰할 수 없는 입력, 그리고 그 둘을 분리할 방법의 부재.

커뮤니티에는 해답이 있습니다. 다만 흩어져 있을 뿐입니다.

이것은 새로운 문제가 아닙니다. 보안 커뮤니티는 수십 년 동안 해답을 써 왔습니다.

역량 기반 보안(Capability-based security) (Dennis & Van Horn, 1966; 이후 E 언어와 Google에서의 Mark Miller의 Caja 작업). 원칙은 이렇습니다. 신원이나 위치를 기준으로 주변 권한(ambient authority)을 부여하지 말고, 프로그램이 다룰 수 있도록 허용된 각 리소스에 대해 명시적이고 위조 불가능한 역량(capability)을 전달하라. 역량은 무엇을 할 수 있는지무엇에 대해 할 수 있는지와 묶으며, 다른 어떤 것과도 혼동될 수 없습니다.

중개된 자격 증명(Brokered Credentials) (OWASP LLM Top 10에서 정립됨). API 토큰을 LLM의 컨텍스트에 넣지 마세요. 신뢰할 수 있는 중간 계층이 에이전트를 대신해 호출합니다. 모델은 무엇을 할지 결정하고, 브로커는 어떻게 할지를 처리합니다. 모델에게 자격 증명을 출력하라고 요청하는 프롬프트 인젝션은 쓸모 있는 것을 아무것도 얻지 못합니다. 자격 증명이 거기에 없기 때문입니다.

팬텀 토큰 패턴(Phantom Token Pattern) (Curity, 원래는 마이크로서비스에서의 OAuth를 위한 것). 에이전트는 실제 베어러 토큰이 아니라 불투명한 세션 핸들을 쥐고 있습니다. 프록시가 그 핸들을 검증하고, 네트워크 엣지에서 실제 자격 증명으로 교체한 뒤 상위로 전달합니다. 에이전트가 자신의 환경을 유출하더라도 공격자가 얻는 것은 세션이 끝나면 만료되는 문자열뿐입니다.

적시 자격 증명 주입(Just-in-time credential injection) (Aembit 같은 워크로드 신원 시스템). 수명이 긴 토큰을 발급하는 대신, 호출마다 수명이 짧고 범위가 좁혀진 자격 증명을 발행합니다.

이 중 어느 것도 문헌에서 빠져 있지 않습니다. 빠져 있는 것은 기본값에서입니다. 대부분의 에이전트 플랫폼은 여전히 중간에 브로커 없이 모델에게 OAuth 토큰을 건네주고는 잘 되기를 바랍니다.

Zero의 브로커가 작동하는 방식

우리는 위의 패턴 중 어느 것도 새로 발명하지 않았습니다. 우리는 그것들을 Zero의 모든 에이전트에 대해 기본으로 실행되는 하나의 브로커로 엮어 냈습니다. 이는 그 패턴들이 설명하는 신뢰할 수 있는 중간 계층이며, AI 에이전트 플랫폼을 위해 만들어졌습니다. 에이전트가 커넥터에 보내는 모든 호출은 이를 거칩니다. 각 커넥터는 하나의 외부 SaaS(Slack, GitHub, Notion 등)입니다.

Broker architecture: agent in Firecracker microVM on the left, the broker in the middle (showing credential isolation, the connector policy gate, and an operational loop with audit), connected to SaaS APIs on the right. A dashed token boundary line shows that real credentials never cross from broker to agent. 브로커는 모든 에이전트와 모든 커넥터 사이에 자리합니다. 실제 자격 증명은 점선의 브로커 쪽에만 존재합니다.

이를 세 개의 계층으로 생각해 보세요.

1. 자격 증명 격리

에이전트의 샌드박스는 실제 커넥터 자격 증명을 결코 쥐고 있지 않습니다. SaaS를 Zero에 연결하면, OAuth 토큰이나 API 키는 브로커 쪽에 존재합니다. 샌드박스는 기존 도구들이 계속 작동할 만큼 환경 시크릿처럼 보이지만, 어떤 상위 SaaS도 받아들이지 않을 플레이스홀더 문자열을 받습니다.

에이전트가 등록된 커넥터 호스트에 요청을 보내면, 브로커는 요청을 매칭하고, 커넥터의 인증 템플릿을 해석하고, 네트워크 엣지에서 실제 자격 증명을 주입합니다. 요청은 유효한 인증과 함께 상위로 전달되며, 에이전트는 쓸모 있는 것을 결코 쥔 적이 없습니다. 환경 변수를 덤프하는 프롬프트 인젝션 에이전트는 공격자에게 SaaS 토큰이 아니라 플레이스홀더를 건넵니다.

이것이 AI 에이전트에 적용된 팬텀 토큰 패턴입니다.

2. 커넥터 정책 게이트

Zero의 커넥터는 단순한 켜고 끄는 스위치 이상이어야 합니다. 각 커넥터는 자신이 다루는 API 베이스와 인증이 어떻게 주입되어야 하는지를 설명합니다. 상위 서비스가 안정적인 스코프-엔드포인트 매핑을 게시하는 경우, 어떤 이름의 권한이 각 메서드와 경로를 다루는지도 설명할 수 있습니다. Slack의 slack-api-ref가 좋은 예입니다.

그래서 Slack에 연결된 에이전트가 chat.postMessage를 호출하면, 브로커는 그 요청을 chat:write에 매핑할 수 있습니다. 감사 로그를 읽으면 그것은 admin.analytics:read입니다. 각 에이전트에 대해 permission_policies는 그 이름의 권한들이 어떻게 동작하는지를 정의합니다. 허용(allow), 거부(deny), 또는 확인(ask). 이 정책은 모델에 대한 힌트가 아니라 인증 주입 이전에 브로커에서 강제됩니다. 에이전트가, 어쩌면 프롬프트 인젝션 때문에, 거부된 권한이 다루는 호출을 시도하더라도, 그 호출은 결코 상위 네트워크에 도달하지 못합니다.

오늘날 모든 커넥터가 그러한 해석 능력을 갖춘 것은 아닙니다. 일부 상위 API는 안정적인 스코프-엔드포인트 매핑을 게시하지 않습니다. GitHub의 GraphQL 영역이 대표적인 사례입니다. REST 쪽은 매핑할 수 있지만 GraphQL 쪽은 아직 할 수 없습니다. 그런 커넥터의 경우에도 브로커는 여전히 자격 증명 주입과 네트워크 경로를 통제하며, 권한 게이트는 플랫폼이 실제로 강제할 수 있는 더 거친 커넥터 또는 호스트 수준 정책으로 폴백합니다. 우리는 상위 데이터가 확보되는 대로 이런 부분을 채워 나갑니다. 우리는 우리가 만들지 않은 커버리지를 주장하지 않습니다.

토큰은 주변 권한을 지니지 않습니다. 권한은 상위가 지원하는 해상도에 맞춰 에이전트마다 중개됩니다. 그것이 해답의 역량 기반 절반입니다.

3. 운영 루프와 감사

최소 권한은 실패 모드가 사용 가능할 때에만 작동합니다. 에이전트는 성장합니다. 6주가 지나면, 처음에 Notion에서 읽기만 하던 리서치 에이전트가 요약을 다시 써넣어야 할 수도 있습니다. 다른 곳에서 흔한 실패 모드는 이렇습니다. 에이전트가 새 권한 없이 조용히 실행되다가 망가지거나, 운영자가 당황해서 권한을 과도하게 부여하고는 다시 회수하지 않는 것이죠.

거부된 커넥터 요청은 구조화된 403을 반환합니다. 커넥터, 메서드, 경로, 베이스 URL, 그리고 브로커가 식별할 수 있을 때는 매칭되는 권한 이름까지요. 에이전트의 시스템 프롬프트는 거부를 진단하는 방법과 방금 부딪힌 바로 그 권한을 요청하는 방법을 에이전트에게 알려 주며, 사용자나 관리자를 위한 원클릭 부여 URL을 생성합니다. 이로써 권한 상승 경로는 "그냥 다 부여하기"로 변질되는 대신 요청되는 정확한 권한에 묶인 채 유지됩니다.

권한 변경 요청은 큐에 쌓입니다. 소유자와 관리자는 대시보드에서 이를 승인하거나 거부할 수 있습니다. 승인된 요청은 에이전트의 정책을 갱신하고, 다음 재시도는 통과합니다. 대부분의 플랫폼은 이 루프를 건너뜁니다. 이것이 없으면 "최소 권한"은 운영 환경에서 돌아가는 대신 슬라이드 덱에 머무릅니다.

같은 브로커 경로가 감사에 데이터를 공급합니다. 실행별 네트워크 로그는 HTTP, TCP, DNS에 걸친 샌드박스 네트워크 활동과 비-TCP 트래픽에 대한 더 낮은 수준의 패킷 관찰을 기록합니다. 커넥터에 매칭된 요청에는 구조화된 브로커 메타데이터가 포함됩니다. 커넥터, 가능한 경우 매칭된 권한, 허용/거부 결과, 인증 해석 메타데이터, 그리고 과금 대상 플래그까지요. 누군가 나중에 "이 에이전트가 화요일 오후 3시에 무엇을 했지?"라고 묻는다면, 그 기록들로부터 답을 재구성할 수 있습니다. 예방은 무언가를 놓칩니다. 감사 추적은 무슨 일이 있었는지 알아내는 방법입니다.

우리가 아직 해결하지 못한 것

위의 모든 것을 갖추더라도, 정당한 chat:write 권한을 가진 에이전트는 이미 접근 권한이 있는 채널에 난처한 메시지를 올리도록 설득당할 수 있습니다. 브로커는 폭발 반경을 좁힐 뿐, 없애지는 못합니다.

해답의 나머지 절반은 고위험 행동에 대한 승인, 출력 검증, 그리고 도구 반환값을 기본적으로 신뢰할 수 없는 것으로 취급하는 것입니다. 그 작업은 로드맵에 있으며, 아직 제품에 들어와 있지는 않습니다. 혼란에 빠진 대리인 문제를 처음부터 끝까지 해결했다고 주장하는 사람이 있다면, 그는 여러분에게 무언가를 팔고 있는 것입니다.

이것은 기능이 아니라 최소 기준이 되어야 합니다

역량 기반 보안은 1970년대부터 존재해 왔습니다. 중개된 자격 증명은 OWASP LLM Top 10에 있습니다. 팬텀 토큰은 LLM 시대 이전부터 있었습니다. 이 중 어느 것도 아무도 해답을 몰라서 빠진 것이 아닙니다. 초기 에이전트 플랫폼들이 "데모가 돌아가게 하기"에 최적화하고 보안을 이후 릴리스로 미뤘기 때문에 빠진 것이며, 그 이후 릴리스는 종종 오지 않았습니다.

다음 세대의 플랫폼들은 더 높은 곳을 지향해야 합니다. 토큰은 모델 컨텍스트에 들어가서는 안 됩니다. 권한은 에이전트마다 열거되어야 합니다. 권한 상승은 사람을 거쳐야 합니다. 모든 행동은 처음부터 끝까지 감사 가능해야 합니다. 이 중 어느 것도 새로운 것이 아닙니다. 이 모두가 기본선이 되어야 합니다.

에이전트 플랫폼을 고를 때 "안전한가요?"라는 질문은 아무 데도 데려다주지 못합니다. 모든 벤더가 그렇다고 답하니까요. 더 나은 질문은 이렇습니다. 당신들의 브로커를 보여 주고, 에이전트가 가지고 있지 않은 스코프를 요청할 때 무슨 일이 벌어지는지 단계별로 설명해 주세요.


브로커는 Zero의 모든 에이전트 앞에 기본으로 자리합니다. 커넥터 목록, 스코프 매핑, 권한 정책, 그리고 브로커 로직 모두 Zero의 소스 저장소에 있습니다. 우리가 다루지 않은 커넥터를 발견하셨나요? 이슈를 등록해 주세요.


참고 문헌

기초

인용된 실제 사건

Related Articles

Stay in the loop

// Get the latest insights on AI teammates and collaboration.

SubscribeJoin Discord