혼동된 대리인과 에이전트 신원
1988년 Hardy가 정의한 혼동된 대리인은 MCP 프록시와 에이전트 위임에서 그대로 재현됩니다. capability 해법, RFC 8693 토큰 교환, 에이전트 전용 신원으로 누가 무엇을 대신했는지 남기는 구조를 정리합니다.
두 출처의 권한을 함께 든 프로그램은 어느 쪽으로 행동하는지 표현할 수단이 없으면 속고, 에이전트가 정확히 그 자리에 있습니다.
두 출처의 권한을 함께 든 대리인
혼동된 대리인(confused deputy)은 Norm Hardy가 1988년에 정의한 개념입니다. 논문은 ACM SIGOPS Operating Systems Review 22권 4호에 실렸습니다. 원 정의는 두 출처의 권한을 지니고 실행되면서 이를 구분할 수단이 없어, 한 주인을 대신하는 사이 다른 권한을 오용하도록 속을 수 있는 프로그램입니다. 논문 제목은 "The Confused Deputy (or why capabilities might have been invented)"입니다. 이 개념은 capability라는 대안을 정당화하려고 정리됐습니다.
사례는 Tymshare 시스템의 FORTRAN 컴파일러였습니다. 이 컴파일러는 자기 홈 디렉터리의 파일에 접근하는 home files license를 지닌 채 실행됐습니다. 사용자가 디버그 출력 파일 이름으로 청구서 파일 (SYSX)BILL을 지정하자, 컴파일러는 그 강한 라이선스로 파일을 덮어썼고 청구 정보가 사라졌습니다.
여기서 권한의 출처는 둘입니다. 하나는 호출자가 RUN (SYSX)FORT로 컴파일러를 실행하며 위임한 권한이고, 다른 하나는 컴파일러 자신의 라이선스입니다. 컴파일러에게는 어느 권한으로 파일을 열려는지 표현할 수단이 없었으므로, 운영체제가 강한 쪽을 적용했습니다.
근본 원인은 주변 권한(ambient authority)입니다. 요청에 권한의 출처가 실려 있지 않으면 시스템은 실행 주체가 가진 권한 전체를 자동으로 적용합니다. 파일 이름은 무엇을 열지만 지정할 뿐, 누구의 권한으로 여는지는 담지 못합니다.
capability가 지정과 권한을 묶는 방식
capability는 대상을 지정(designation)하면서 동시에 권한(authorization)을 부여하는 참조입니다. 지정과 권한이 하나로 결합되므로 이름을 받아 별도로 권한을 검사하는 단계가 사라집니다. 컴파일러가 호출자에게 받은 capability로만 출력 파일을 열었다면, 청구서 파일에 대한 capability가 없어 그대로 실패했을 것입니다.
접근제어 목록(Access Control List, ACL) 기반 접근제어로는 이 공격이 막히지 않습니다. ACL은 요청한 주체에게 그 자원의 권한이 있는지만 확인하는데, 대리인은 실제로 그 권한을 갖고 있기 때문입니다.
| 구분 | ACL | capability |
|---|---|---|
| 요청에 담기는 것 | 대상 이름 | 대상과 권한이 결합된 참조 |
| 권한 판정 근거 | 실행 주체가 가진 권한 전체 | 요청에 실린 capability |
| 혼동된 대리인 | 막지 못함 | 막음 |
Hardy가 당대에 제시한 임시방편은 switch hats라는 시스템콜이었습니다. 대리인이 자기 권한과 호출자 권한 중 무엇으로 행동할지 매번 명시적으로 고르게 하는 방식이고, 오늘날의 on-behalf-of 위임이 이 발상의 원형입니다.
Hardy 자신은 이 방식을 불충분하다고 평가했습니다. 실제 애플리케이션은 둘 이상의 권한을 동시에 필요로 했고, 두 값 중 하나를 고르는 모델은 그 상황으로 일반화되지 않았습니다. 위임을 주체와 행위자 두 값만으로 표현할 때의 한계는 1988년에 이미 지적된 셈입니다.
MCP 프록시에서 되살아난 경로
에이전트 스택은 이 구조를 그대로 재현합니다. MCP(Model Context Protocol) 서버나 프록시는 사용자 토큰을 받아 자신의 자격증명으로 하위 API를 호출하는 자리에 있습니다. 두 출처의 권한을 함께 들고 있으면서 요청마다 어느 쪽으로 행동하는지 남기지 않으면, 1988년의 컴파일러와 같은 위치가 됩니다.
MCP 보안 지침은 첫 변형을 토큰 통과(token passthrough)로 부르고 안티패턴으로 금지합니다. 자신에게 발급된 토큰인지 검증하지 않은 채 받은 토큰을 하위 API로 그대로 넘기는 동작입니다. 이때 서버가 걸어 둔 통제가 우회되고, 감사 기록의 주체가 흐려지며, 같은 토큰이 다른 서비스에서 재사용됩니다.
| 클레임 | 들어온 토큰 | MCP 서버가 기대해야 할 값 |
|---|---|---|
| aud | https://storage-api.example | https://mcp-proxy.example |
| scope | files.read.all | files.read.project |
프록시가 aud와 actor를 검사하지 않고 전달하면, 하위 저장소 API는 이 요청을 프록시의 정상 호출로 받아들입니다. 로그에서 이 흐름을 잡는 단서는 같은 jti와 같은 토큰 해시가 프록시 앞뒤 두 구간에 그대로 나타나는 것입니다.
두 번째 변형은 OAuth 혼동된 대리인입니다. 프록시가 제3자 API에 단일 정적 client ID로 동작할 때, 아래 네 조건이 동시에 충족되면 성립합니다.
- 제3자 인가 서버에 정적 client ID를 사용
- MCP 클라이언트의 동적 등록을 허용
- 제3자가 최초 인가 후 동의 쿠키를 설정
- 프록시가 포워딩 전에 클라이언트별 동의를 강제하지 않음
동의 쿠키는 사용자가 한 클라이언트에 준 허락의 흔적인데, 프록시가 그것을 모든 클라이언트에 재사용하면서 경계가 무너집니다. 사용자 동의는 요청한 클라이언트에만 한정돼야 하고, authorization code는 등록된 callback으로만 가야 합니다. 두 변형 모두 누가 누구를 대신해 어떤 자원을 호출하는지가 사라집니다.
RFC 8693이 위임을 표현하는 방식
RFC 8693 OAuth 2.0 Token Exchange는 2020년 1월 IETF 제안 표준(Proposed Standard)이 됐습니다. 이 명세는 위임(delegation)과 사칭(impersonation)을 갈라 정의합니다. 위임은 행위자 A가 자기 정체성을 유지한 채 B를 대표해 행동하는 것이고, 사칭은 A가 B의 모든 권리를 받아 B와 구별되지 않는 상태입니다.
RFC 8693은 두 의미를 모두 지원합니다. on-behalf-of라는 표현이 붙었다고 자동으로 위임이 되지는 않습니다. Microsoft의 on-behalf-of(OBO)처럼 사칭에 가까울 수 있는 구현도 있으므로, 위임을 원한다면 명시적으로 골라야 합니다.
위임 사슬은 두 파라미터와 한 클레임으로 표현합니다. subject_token은 대신하는 대상을, actor_token은 실제 행위자를 담습니다. 발급된 JWT의 act 클레임을 중첩하면 최외곽이 현재 행위자, 안쪽이 이전 행위자가 되어 도구 호출과 하위 에이전트 재위임이 사슬로 남습니다.
접근제어 판정에서 중첩된 이전 행위자는 참고 정보일 뿐입니다. 토큰을 소비하는 쪽은 최상위 주체와 현재 행위자만 보고 결정합니다. 사슬 전체는 감사용 계보이고, 인가 판단은 현재 홉에서 끝납니다.
RFC 8693은 서비스 체인과 위임 홉을 명시적으로 지원합니다. 자원 서버가 받은 토큰을 백엔드 호출용 새 토큰으로 교환하면서 스스로 클라이언트 역할을 맡는 구조입니다. 하위 도구와 하위 에이전트로 권한이 내려가는 에이전트 스택과 직접 대응하므로, 현재 표준 가운데 에이전트 위임에 가장 가깝습니다.
교환할 때마다 scope, resource, audience로 발급 토큰을 좁히는 다운스코핑이 방어의 축입니다. Microsoft OBO는 위임 scope만 전파하고 애플리케이션 역할은 사용자 주체에 고정해 앱으로 넘기지 않습니다. 또한 assertion 토큰의 aud가 OBO를 요청한 앱과 일치해야 하며, 다른 자원용으로 발급된 토큰은 교환이 거부됩니다. audience 제한이 곧 토큰 재사용 차단입니다.
재위임의 사전 통제로는 may_act 클레임이 있습니다. 어떤 당사자가 다른 당사자를 대신해 행위자가 될 자격이 있는지를 토큰 발급 시점에 미리 인가합니다. 어느 에이전트와 도구가 사용자를 대신할 수 있는지 경계를 정책으로 거는 장치입니다.
Microsoft OBO는 RFC 8693의 token-exchange 그랜트를 쓰지 않습니다. RFC 7523 jwt-bearer 그랜트에 requested_token_use=on_behalf_of 파라미터를 얹은 독자 메커니즘입니다. 이름이 비슷해도 IETF 표준 토큰 교환과 별개이므로 상호 운용을 전제하면 안 됩니다.
에이전트 전용 신원
위임을 형식화해도 행위자 자리에 넣을 신원이 없으면 사슬이 비어 있습니다. 에이전트에 사람 계정이나 공용 서비스 계정을 그대로 쓰면 감사 기록에는 사람만 남고 실제로 행동한 주체는 사라집니다. 비인간 신원(Non-Human Identity, NHI)은 이 자리를 채우는 계층입니다.
Microsoft가 에이전트 신원을 별도로 두는 근거로 든 것은 네 가지입니다.
- 에이전트 작업을 인력·고객·워크로드와 구분해 귀속시킵니다. 모든 질의가 어느 에이전트가 수행한 것인지로 기록됩니다.
- 하루에 수천 번 생성되고 사라지는 대규모 단명 수명주기를 관리합니다.
- 적응형 접근, 위험 탐지, 수명주기 관리 같은 IAM 보호를 사람 계정과 같은 수준으로 적용합니다.
- 에이전트마다 최소 한 명의 인간 스폰서를 두고, 스폰서가 조직을 떠나면 매니저에게 자동 이관합니다.
워크로드 신원 표준으로는 CNCF 졸업 프로젝트인 SPIFFE가 있습니다. SPIFFE ID는 RFC 3986 URI 형식 spiffe://<trust-domain>/<path>를 따릅니다. scheme은 spiffe여야 하고, trust domain은 비어 있을 수 없으며, query와 fragment는 금지되고, 전체 길이는 2048바이트 이하입니다.
SVID는 SPIFFE ID에 서명과 선택적 공개키를 붙인 문서이고 워크로드 API로 발급됩니다. 하드코딩한 자격증명 대신 단명 기계 신원을 쓰게 되며, mTLS나 JWT로 상호 인증합니다. 해당 신뢰 도메인의 권한이 서명해야만 유효하고, 구현체로는 SPIRE가 있습니다.
Microsoft Entra Agent ID는 같은 문제를 IAM 제품 쪽에서 다룹니다. 서비스 주체(Service Principal)와 구별되는 전용 신원입니다. 서비스 주체는 장기 안정성을 전제하지만, 에이전트 신원은 규모와 단명성을 전제로 설계됐습니다. 구현은 서비스 주체 인프라 위의 agent 하위 유형입니다. 객체는 blueprint, blueprint principal, agent identity, agent user 네 개입니다.
권한은 최소로 시작합니다. blueprint에서 상속한 위임 scope로 출발하고, 필요하면 access package로 넓힙니다. 에이전트는 대화형 /authorize 화면을 직접 열 수 없으므로 클라이언트가 사용자 토큰을 받아 OBO로 교환해 넘깁니다. 다만 2026년 7월 기준 이 기능은 preview 단계이고 프리미엄 라이선스로 게이팅됩니다.
프로토콜 계층은 아직 뒤에 있습니다. Microsoft는 A2A 지원을 발표하며 A2A와 MCP의 기업급 신원 지원을 업계와 함께 설계 중이라고 밝혔습니다. 이 발언 자체가 해당 계층의 신원과 인증이 표준화 이전임을 보여 줍니다. 지금은 프로토콜 바깥의 게이트웨이와 인가 서버가 그 공백을 메워야 합니다.
운영 체크리스트
혼동된 대리인을 잡으려면 토큰 원문보다 그 주변 값을 남겨야 합니다. actor, audience, scope, 동의 계보가 실제 보안 데이터입니다.
남길 로그
- 토큰 해시와
iss,sub,actor,aud,scope,tenant,exp,jti클레임 - 최초 요청의
client_id, redirect URI, 동의 기록 - 토큰 교환의 부모-자식 계보와 하위 호출 수신 기록
탐지 신호
- audience 불일치, actor 누락이나 변경
- 위임 홉을 지나면서 scope가 늘어난 경우
- 같은 토큰이 여러 클라이언트에서 쓰인 경우
- 처음 보는 redirect URI, 동의 기록 없는 authorization code 발급
차단 지점
- MCP 서버 전용 audience를 가진 토큰만 수용
- RFC 8707 Resource Indicators로 토큰의 대상 자원 결속
- 전달 대신 토큰 교환과 다운스코핑
- 클라이언트별 동의, redirect URI 정확 일치, 짧은 TTL과 소유 증명(proof-of-possession)
통제가 뚫렸는지는 세 가지 비교로 판정합니다. 아래 중 하나라도 해당하는 트랜잭션이 성공했다면 경계가 무너진 것입니다.
- 실제 행위자가 승인된 행위자와 다름
- 호출된 자원이 승인된 자원과 다름
- 유효 scope가 승인된 scope의 부분집합이 아님
정리
혼동된 대리인은 두 출처의 권한을 함께 든 프로그램이 어느 쪽으로 행동하는지 표현하지 못할 때 생깁니다. Hardy는 1988년에 지정과 권한을 묶는 capability로 그 틈을 닫았고, 에이전트 스택은 같은 틈을 MCP 프록시에서 다시 엽니다. 토큰을 검증 없이 하위 API로 넘기거나 동의 쿠키를 모든 클라이언트에 재사용하면 사용자 권한이 그대로 새어 나갑니다.
RFC 8693은 위임을 프로토콜 수준에서 표현하는 현재 가장 가까운 표준입니다. subject_token과 actor_token, 중첩 act 클레임, 다운스코핑, may_act가 그 수단입니다. 남은 절반은 신원이므로, SPIFFE나 Entra Agent ID로 에이전트에 별개 신원을 주고 actor와 audience와 동의 계보를 로그에 남겨야 합니다.