A2A 프로토콜의 신원 인증 공백 문제
요약
A2A 프로토콜에서 에이전트 간 신원 인증(Identity Verification)이 결여된 보안 취약점을 분석합니다. 현재 프로토콜은 에이전트 카드의 정당성을 증명할 암호화 검증 수단이 없어, 신원 위조 가능성이 존재함을 지적합니다.
핵심 포인트
- A2A 프로토콜 내 에이전트 카드 신원 검증 메커니즘 부재
- 전송 계층 보안(mTLS 등)만으로는 에이전트 정체성 증명 불가
- 공개 키 결합, 서명, 검증 단계의 필수 도입 필요성
- 프로토콜 명세 내 일급 객체로서의 identity 필드 추가 제안
문제가 발생하는 지점은 바로 이것입니다: 당신의 에이전트(Agent)가 방금 다른 에이전트와 계약에 동의했습니다. 하지만 그 에이전트가 주장하는 본인이 맞는지 당신은 전혀 알 수 없습니다.
A2A 프로토콜은 핸드셰이크(Handshake)를 처리합니다. 에이전트들이 서로를 어떻게 발견하고, 역량(Capabilities)을 교환하며, 메시지를 전달하는지를 정의합니다. 하지만 명세(Spec)에는 커다란 구멍이 있습니다. 프로토콜 수준에서 에이전트 카드(Agent Card)가 정당한지 증명할 방법이 전혀 없다는 것입니다.
누구든지 "나는 Acme Corp의 재고 관리자입니다"라고 주장하는 에이전트 카드를 만들어낼 수 있습니다. 당신의 에이전트는 그것을 신뢰할 것입니다. 그것이 바로 문제입니다.
격차 (The Gap)
현재의 흐름은 다음과 같습니다:
- 에이전트 A가 에이전트 B의 에이전트 카드를 가져옵니다.
- 에이전트 A가 메타데이터(Metadata) — 이름, 설명, 기술, 엔드포인트(Endpoints)를 읽습니다.
- 에이전트 A가 요청을 보내기 시작합니다.
그게 전부입니다. 암호화 검증(Cryptographic verification)도 없습니다. 에이전트 B가 실제로 그 카드 뒤에 있는 엔티티(Entity)라는 증거도 없습니다.
명세에서는 신원 검증(Identity verification)을 "외부 메커니즘에 맡긴다"라고 명시하고 있습니다. 이는 "우리는 이 문제를 해결하지 못했다"라고 정중하게 말하는 것과 같습니다.
전송 계층 신뢰(Transport-layer trust) (mTLS, 서명된 URL)는 채널(Channel) 보안에는 도움이 됩니다. 이는 바이트(Bytes)가 특정 서버에서 왔음을 증명합니다. 하지만 해당 서버 뒤에 있는 에이전트가 당신이 대화하고 있다고 생각하는 바로 그 에이전트임을 증명하는 데는 아무런 도움이 되지 않습니다.
실제로 누락된 것
당신에게는 세 가지가 필요합니다:
- 에이전트 카드에 결합된 공개 키 (Public key)
- 카드의 핵심 필드에 대한 서명 (Signature)
- 모든 상호작용 전의 검증 단계 (Verification step)
익숙하게 들리시나요? 이것은 기본적으로 HTTPS가 작동하는 방식과 같습니다. 하지만 에이전트를 위한 방식이죠.
수동 해결 방법 (The Manual Fix)
오늘 당장 이를 임시로 구현(Hack)할 수 있습니다. 에이전트 카드의 extensions 필드에 공개 키를 저장하고 메시지를 수동으로 검증하십시오.
{
"name": "Inventory Manager",
"description": "Manages warehouse stock",
...
그런 다음 수신 측에서 모든 메시지의 서명을 검증합니다:
import crypto from 'node:crypto';
function verifyAgentMessage(
...
이 방식은 작동합니다. 하지만 취약합니다. 당신은 관습(convention)을 만들어내고 있는 것입니다. 모든 에이전트가 이를 다르게 구현할 것이며, 어떤 에이전트는 아예 구현하지 않을 수도 있습니다. 또한 악의적인 행위자가 카드에 자신만의 키를 넣고 자신만의 거짓 정보를 서명하는 것을 막을 방법이 없습니다.
키는 어딘가에 고정(anchored)되어야 합니다. 당신의 에이전트가 독립적으로 검증할 수 있는 어딘가에 말입니다.
프로토콜이 해야 할 일
A2A 명세(spec)에는 일급 객체(first-class) 신원 필드가 필요합니다. 확장(extension)이 아니라, 정의된 의미론(semantics)을 가진 적절한 필드여야 합니다.
저의 제안은 다음과 같습니다:
- Agent Card 명세에
identity추가 — 공개 키(public key)와 발행자(issuer)에 대한 참조를 포함합니다. - 서명 스킴(signature scheme) 정의 — 카드의 정형화된 JSON 표현(canonical JSON representation)에 대해 정의합니다.
- 검증 요구 — 선택적 단계가 아닌, A2A 핸드셰이크(handshake)의 일부로 요구합니다.
다음과 같은 형태입니다:
{
"name": "Inventory Manager",
"url": "https://acme.com/agents/inventory",
...
issuer 필드가 핵심입니다. 이는 DID 또는 WebPKI 스타일의 신뢰 앵커(trust anchor)를 가리킵니다. 당신의 에이전트는 이를 해석(resolve)하고, 키의 폐기 상태(revocation status)를 확인한 다음, 카드를 신뢰할지 여부를 결정할 수 있습니다.
검증 단계
카드가 신원을 갖게 되면, 핸드셰이크가 다음과 같이 변경됩니다:
async function verifyAgentCard(card: AgentCard): Promise<boolean> {
// 1. 발행자의 공개 키를 가져옵니다
const issuerDoc = await resolveIssuer(card.identity.issuer);
...
이것이 루프를 완성합니다. 당신의 에이전트는 단순히 카드를 액면 그대로 받아들이지 않습니다. 카드가 신뢰할 수 있는 발행자로부터 왔는지, 서명이 유효한지, 그리고 키가 폐기되지 않았는지를 검증합니다.
대안
지금 하고 있는 방식을 계속하십시오. 전송 계층(transport layer)을 신뢰하십시오. 아무도 카드를 위조(spoof)하지 않기를 바라십시오. 당신의 에이전트가 가짜 엔드포인트(endpoint)로 민감한 데이터를 보내도록 속임을 당하지 않기를 바라십시오.
이것은 표준 수준(standards-level)의 문제입니다. A2A 명세는 에이전트가 실제 돈, 실제 계약, 실제 데이터를 다루기 시작하기 전에 이 문제를 해결해야 합니다. 왜냐하면 현재 가장 취약한 연결 고리는 모델이 아니기 때문입니다. 바로 신뢰 모델(trust model)입니다.
적절한 구현이 이를 엔드 투 엔드 (end-to-end)로 어떻게 처리하는지 확인하고 싶으신가요? TracePilot가 실제 운영 환경에서 에이전트 신원 인증 (agent identity verification)을 어떻게 계측하는지 확인해 보세요. 트레이스 (trace)를 포크하여 신뢰가 정확히 어디에서 깨지는지 확인하고, 비용이 발생하기 전에 이를 수정하십시오.
AI 에이전트를 디버깅하는 것이 마치 매트릭스 (The Matrix)를 읽는 것처럼 느껴져서는 안 됩니다.
저희 커뮤니티에서 신뢰할 수 있는 자율 워크플로우 (autonomous workflows)를 구축하고 있는 다른 엔지니어들과 함께하세요: TracePilot Discord
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기