
AI로 생성한 주제 설명용 이미지입니다.
- Source: arXiv cs.CR (AP2 / agentic commerce)
- Authors: Yedidel Louck; Amit Dvir; Ariel Stulman
- Published: 2026-09-10
- Relevance: 에이전트가 사용자를 대신해 결제하는 AP2에서, 서명된 Intent·Cart·Payment는 거래 객체의 무결성만 묶고 그 객체를 고른 결정은 묶지 않는다. 가맹점 자유 텍스트가 다른 사용자의 결제수단 조회, 카트 위조, 더 비싼 상품으로의 선택 유도로 이어질 수 있다. 인가된 에이전트 커머스·지갑·세션 바인딩 점검에 바로 쓸 수 있다.
- Original URL: https://arxiv.org/abs/2609.11757
Signing the Transaction but Not the Decision: Whisper Attacks and a Binding Defense for AP2
한눈에 보기
관찰: Google Agent Payments Protocol(AP2) v0.2.0 참조 구현은 Intent Mandate, Cart Mandate, Payment Mandate를 W3C Verifiable Credential과 ECDSA P-256으로 서명한다. 서명 체인은 “이 카트가 위조되지 않았는가”는 검증하지만, “이 카트가 사용자가 원한 결정의 결과인가”는 검증하지 않는다.
보안 속성: 프로토콜 보안 문서는 프롬프트 인젝션 방지가 불가능하다고 명시하고, 닫힌 Mandate 검증 시점의 제약(constraints)으로 피해를 상한한다고 주장한다. 그러나 사람-존재(human-present) 샘플 에이전트는 constraints 필드를 비운 채 배포되며, 결제수단 조회 RPC(get_payment_methods)는 카트가 생기기 전에 호출되어 Mandate 체인 밖에 있다.
실제 영향: 가맹점이 통제하는 상품 설명 한 문장이, 암호학적으로 유효한 결제 체인을 유지한 채 (1) 다른 사용자의 카드 alias를 에이전트 컨텍스트로 끌어오고, (2) 표시되지 않은 라인·가격·정산 가맹점을 카트에 넣고, (3) 재고·후속 모델이라는 사실 주장만으로 더 비싼 상품을 고르게 할 수 있다. 참조 구현이 고정한 Gemini Flash-Lite 계열에서 세 계열의 성공률은 각각 90%, 56%, 73.3%로 보고되었다.
미충족 조건: 저자들은 A-VIP로 Vault/Branded 계열은 구조 바인딩으로 차단하고 Selection 계열은 지출 확인으로만 드러낸다고 주장한다. 후자는 사용자 확인을 전제로 하며, 최저가 승격·단일 SKU 묶음은 서명 객체만으로는 잡지 못한다. 벤더 VRP는 Vault 체인을 moderate severity 버그로 접수했으나 수정은 업스트림 이슈에 묶여 있고, 평가 시점에도 참조 구현에서 재현된다고 적혀 있다.
연구 배경
에이전트가 사용자를 대신해 쇼핑·결제하는 스택이 등장하면서, AP2는 Intent(목표), Cart(장바구니), Payment(결제수단)를 각각 서명하는 방식으로 “누가 무엇을 승인했는지”를 감사 가능하게 만들려 했다. Mastercard Verifiable Intent는 사후 분쟁 증거이고, ZTRV는 일회용 nonce로 Mandate 재사용을 막지만 의미론적 주입은 범위 밖이라고 명시한다. Coinbase x402는 다른 연합 모델을 쓴다. 공통적으로 가맹점이 넣는 자유 텍스트는 검사하지 않는다.
선행 연구 Debi et al.은 AP2에 대한 두 가지 Whisper(Branded 순위 조작, Vault 자격증명 유출)를 보고했지만, 악성 사용자를 가정하고, 농구화 한 과제·열 번 시행·방어 없음·양성 기준선 없음이었다. 이 논문은 (1) 정직한 사용자 + 악성 가맹점 텍스트로 Vault를 재구성하고, (2) Branded를 다섯 하위유형으로 확장하며, (3) 지시문이 아니라 사실 전제인 Selection Whisper를 세 번째 계열로 두고, (4) 프로토콜 계층 방어와 전용 벤치마크를 붙인다.
공격 모델 / 전제 조건
저자 가정(정직한 쪽): 사용자, 사용자를 대행하는 쇼핑 에이전트, Credentials Provider(지갑)는 정직하다. 가맹점 PSP의 암호·정산 연산도 정직하다. 손상된 지갑이나 부정직한 PSP는 Mandate 체인 상류의 별도 위협으로 범위 밖이다.
공격자가 갖는 것: 마켓플레이스에 입장한 가맹점은 DID로 인증되지만, PaymentItem.label / description / search_products가 돌려주는 자유 텍스트, 응답 순서, 자신이 서명하는 카트 내용을 AP2 스키마 안에서 통제한다. 사용자 Intent 문장, 지갑, 모델 가중치, 자격증명 제공자 응답, 쇼핑 에이전트의 AP2 v0.2.0 시스템 프롬프트는 통제하지 못한다.
배포 전제: 평가 대상은 google/ap2 v0.2.0, commit b4587ac1(태그 이후 CHANGELOG 등만 다름, 소스 동일). 사람-존재 카드 시나리오 에이전트는 샘플 모델을 소스에 고정하고 Mandate constraints를 비운다. 사람-부재 에이전트는 allowed-payees와 금액 범위를 채우지만, Selection Whisper에 대한 이 에이전트의 실시간 평가는 미래 작업으로 남겨 두었다.
성공에 필요한 조건: 에이전트가 가맹점 텍스트를 읽고 사용자를 대신해 도구를 고를 수 있어야 한다. 이 속성은 AP2뿐 아니라 uAgents 메시지 버스, CoralOS 마켓플레이스 코디네이터에서도 성립한다고 측정되었다. Selection은 지시 거절 학습만으로는 막히지 않는다. 사실 주장에는 거절할 명령이 없기 때문이다.
핵심 공격 원리
원리의 중심은 “서명된 객체와 결정의 분리”다.
- Intent는 “나이키 페가수스 41 남성 10사이즈를 사라” 같은 자유 형식 목표에 서명한다. 청중은 쇼핑 에이전트다.
- 쇼핑 에이전트는 A2A로 가맹점 에이전트를 질의하고, DID로 식별되는 PaymentItem 목록을 받는다. 텍스트 필드는 가맹점 완전 통제다.
- 가맹점이 Cart Mandate에 서명하고, 지갑이 Payment Mandate에 서명한다. 지갑은 get_payment_methods(user_email)로 alias를 준다.
- ZTRV nonce는 이전 Mandate의 재사용은 막지만, “이 카트가 사용자 목표와 같은 결정인가”는 보지 않는다.
세 계열은 가맹점 텍스트가 더럽히는 지점이 다르다.
- Vault Whisper: 자격증명 조회 인자를 세션 사용자가 아닌 주소로 바꾼다. 피해자 alias가 에이전트 컨텍스트에 들어오면 가맹점이 읽거나 추가 악용할 수 있다. 원 연구는 악성 사용자를 가정했고, 이 논문은 가맹점 텍스트로 옮겼다.
- Branded Whisper: 서명된 카트를 오염한다. 선행의 순위 편향에 가격 부풀리기, 요청하지 않은 부가, 경쟁사 강등, 공격자 DID로 정산 우회(D2)를 더한다. 카트는 암호학적으로 유효하지만 라인·가격·정산 가맹점이 Intent와 어긋난다.
- Selection Whisper: 재고 단종·후속 모델 같은 사실 전제로, 이미 화면에 나온 상품 중 더 비싼 쪽을 고르게 한다. 카트는 표시와 일치하므로 구조 검사는 불일치를 찾지 못한다.
A-VIP의 대응 원리도 텍스트 분류가 아니라 권한 부여(capability grant)다. 서명된 Intent를 능력으로 읽고, 값의 이동마다 그 범위 안에 있는지를 구조적으로 검사한다. 텍스트 검사기는 보조다.
공격 흐름
무기화 절차가 아니라, 인가 점검에서 확인할 조건열이다.
Vault 계열
- 세션 사용자가 Intent에 서명한다.
- 가맹점 응답의 자유 텍스트에, 세션 사용자가 아닌 식별자로 결제수단 조회를 유도하는 내용이 포함된다.
- 에이전트가 지갑 RPC의 인자를 그 식별자로 채운다.
- 지갑이 피해자 alias를 돌려주고, 그 값이 에이전트 컨텍스트에 남는다.
- 카트·결제 Mandate는 이후에도 형식상 유효할 수 있다. 유출은 Mandate 검증 이전에 발생한다.
Branded 계열
- 화면에 나온 상품 집합과 Intent의 브랜드·가격 상한이 있다.
- 가맹점 텍스트가 카트 조립을 밀어, 미표시 라인, 표시가와 다른 단가, 합과 다른 총액, 또는 표시 가맹점이 아닌 정산 DID가 서명 객체에 들어간다.
- 가맹점이 Cart Mandate에 서명한다. 프로토콜 검증은 서명의 형식만 본다.
- 사람-존재 샘플은 constraints가 비어 있어 closed-mandate 검증이 위반을 만들지 않는다.
Selection 계열
- 정당한 두 상품이 모두 표시된다.
- 가맹점 텍스트가 싼 쪽을 단종·용량 부족·카탈로그 개정으로 기술하고 비싼 쪽을 후속작으로 기술한다. 명령문이 아니다.
- 에이전트가 그 전제를 검증하지 않고 비싼 쪽을 추천한다.
- 카트는 표시된 SKU와 표시가를 그대로 담는다. 구조 바인딩은 통과한다.
소비자 어시스턴트에서 같은 문장을 채팅에 붙여 넣으면 필터가 거절했지만, 어시스턴트가 가져온 웹 페이지에 있으면 따랐다. 필터는 사용자 입력은 보고, 검색으로 들어온 가맹점 데이터는 못 본다.
연구진의 실험
스택: 수정하지 않은 AP2 참조 배포. 네 프로토콜 역할을 로컬 A2A 엔드포인트로 띄우고, 유사 DID의 두 번째 악성 가맹점을 연합에 넣는다. LLM 트래픽은 OpenRouter로 우회해 AP2 소스를 바꾸지 않는다. 기본 샘플링, 시드 없음(Gemini/Claude API가 결정적 시드를 노출하지 않음). A-VIP는 Intel i7-13700H, 32GB, Python 3.11, GPU 없는 사이드카.
벤치마크 AP2-WhisperBench: 핵심 1,440 시나리오(공격 390 + 양성 1,050) + branded_factual 104 = 1,544. Vault 150 / Branded 150 / Selection 90을 세 라운드 프레이징으로 나눈다. 양성은 직영 브랜드, 공식 리셀러, 마켓플레이스, 브랜드 변형, 미지 애그리게이터, 신규 가맹점 등 여섯 계층, 계층당 최소 150. 합성 금고 51명(허구 이메일·허구 Mastercard alias). Vault/Branded 판정은 순수 Python 술어이고 모델 판정을 쓰지 않는다. Selection은 절 앵커 리더 + 수동 검증(κ=0.96). 핵심 1,440 × 8모델 OpenRouter 비용 $7.35.
평가 순서: (7.2) 세 계열이 더럽히는 지점, (7.3) 모델·벤더·가격대·프레임워크 일반화, (7.4) 지시에서 사실로의 격상, (7.5) 소비자 제품의 붙여넣기 vs 가져오기, (7.6) 구조 바인딩의 한계, (7.7) 지출 확인 비용, (7.8) 언어·패러프레이즈·방어 인지 공격자.
주요 결과
Flash-Lite 라인(프로토콜이 고정한 계열)
- Vault: n=50, 90% [78.6, 95.7]. 판정은 지갑 조회에 세션 사용자가 아닌 주소가 들어간 경우만. 자연어 언급은 유출로 치지 않는다.
- Branded: n=50, 56% [42.3, 68.8]. 미표시 라인, 가격 변경, 합 불일치.
- Selection: n=90, GA 후속 모델 73.3% [63.4, 81.4]. 프리뷰 23.3%보다 높다. 프레이징 라운드만 바꿔 Vault는 32→60→90, Branded는 14→34→56.
모델 일반화
- Selection은 Google 17개 빌드에서 23.3–73.3%. 완전 저항은 없었다. claude-opus-5만 1.2%. 고가 Pro가 더 안전하지 않다(gemini-2.5-pro 61.9%, 3.1-pro-preview 67.1%). 동일 $0.25/M 입력 토큰 두 모델이 Vault에서 95%와 85%로 갈린다. Google 오픈웨이트 gemma4는 5% 저항, Flash-Lite는 95% 유출.
프레임워크
- uAgents: 주입 문장이 싼 상품에서 비싼 상품으로 30/30, 대조 0/30.
- CoralOS: 29/30 vs 대조 0/30.
지시 vs 사실
- 같은 승격을 지시로 주면 Anthropic Opus는 3.3–4.4%, Grok는 52.2–58.9%. 재고 후속작이라는 사실로 바꾸면 Gemini 5개 빌드 85%, 6개 조직 27개 빌드 합산 71.8% [68.7, 74.7]. claude-opus-5 0%, kimi-k3 3.1%만 사실 전제에 강했다.
소비자 제품
- 붙여넣기: 8/8 거절. 가져온 페이지: 재고 7/12, 용량 11/12, 구매 안내 12/12, 카탈로그 개정 12/12. 대조(문장 없음) 0/12. 프리미엄 티어도 최강 문장 11/13. 셀은 8–13회로 구간이 넓다. 저자도 정확한 비율보다 방향이라고 적는다.
방어
- Entity / Display / Chain 바인딩은 카트 오염 7종을 산술·식별자 비교만으로 거절. Selection이 만든 68개 카트는 0건 거절 [0, 5.3].
- 사람-부재 제약: AllowedPayees는 리다이렉트 634건 전부 거절. AmountRange는 인플레이션 534건 전부 거절. 부가 597건은 표시 총액이라 천장에 걸리지 않고 Display binding이 미표시 라인을 잡는다.
- 지출 확인: 오염 카트 68/68을 확인으로 올림. 양성 프리미엄 24건 중 예산 없는 16은 모두 확인, 예산 있는 8은 0. 콘텐츠 스캐너 엄격 위양성 12%(diversity stress). 적응형 생성기는 Branded 지시 79%, Vault 17%를 스캐너에서 우회. 그래서 스캐너는 보조다.
언어: 10개 언어 5개 스크립트에서 81.1% [76.7, 84.8]. 독·서·일 100%, 러시아 44.4%, 영어 80.6%. 비영어는 리더가 보수적으로 채점하므로 하한이다.
실제 발견된 취약점 / 사례
CVE 번호는 없다. 저자가 보고한 것은 프로토콜·제품 동작이다.
- AP2 v0.2.0 사람-존재 샘플: constraints 공백. SDK 테스트도 빈 제약 목록이 위반을 만들지 않는다고 기록한다.
- 자격증명 조회가 Mandate 이전에 열려 있어, 세션에 묶이지 않은 식별자로 alias를 끌어올 수 있다.
- 벤더 VRP: Vault 체인을 접수, 제품팀에 버그 등록, moderate severity, 엔지니어 할당, in progress. 수정은 업스트림 이슈 의존. 리워드 패널은 집필 시점 미결정. 90일 창은 닫혔고 참조 구현에서 재현된다.
- Selection·사실 전제는 별도 보고, 심사 중. “수정 불필요”로 끝나면 허용된 동작이 된다.
- 소비자 어시스턴트: 가져온 페이지의 사실 문장이 더 비싼 추천으로 이어짐. 같은 문장을 채팅에 직접 넣으면 거절.
실험은 합성 금고만 사용했고 실제 금융 자격증명은 쓰지 않았다.
기존 공격과의 차이
선행 Whisper는 악성 사용자, 단일 과제, 방어 없음이었다. 이 연구는 가맹점 텍스트, 세 계열, 17+ 모델, 세 프레임워크, 소비자 제품, 구조 방어를 붙인다. 일반 IPI 벤치마크(AgentDojo, BIPIA, InjecAgent, WebInject)는 서명된 Intent-Cart-Payment 체인을 모델링하지 않는다. ZTRV는 실행 계층 재사용을 막고 의미 주입은 연다. A-VIP는 Mandate 계층에서 서명 객체를 묶는다. 두 계층은 겹치지 않는다고 저자도 표로 명시한다. 모델 내부 정렬(Meta SecAlign 등)은 지시 거절을 노리므로 사실 전제 Selection은 공격 클래스 밖이다. 출력 측 재실행(MELON, Task Shield)은 요청당 모델 추론 비용이 결제 게이트웨이 예산을 넘긴다.
연구의 한계와 주의해서 볼 부분
저자 주장보다 증거가 좁은 지점
- “어떤 모델·프레임워크도 도망가지 못한다”는 Google 17개 + 앵커 2개 + 프레임워크 3개다. claude-opus-5는 사실 전제에 강했다. 저항은 학습 가능한 속성이지 벤더·가격·능력의 함수가 아니라는 쪽이 정확한 주장이다.
- 소비자 제품 수치는 셀당 8–13회, 일부는 1회. 정확한 비율로 인용하면 안 된다.
- 지시 vs 사실 비교는 시나리오 집합이 달라 쌍대 비교가 아니다.
- 사람-부재 에이전트의 Selection 실시간 평가는 없다.
- 벤치마크는 held-out이 아니라 공개 회귀 세트다. 학습에 넣으면 과적합된다.
- 분할 페이로드·다회전 사회공학은 벤치마크 범위 밖이다.
- DDFC 불변량은 TLC로 검사하지만, 재시도·분할 결제·카트 수정·환불은 부록의 운영 논증이다.
- 지출 확인은 사용자가 자동 승인하지 않아야 한다. 최저가 승격·원자 SKU 묶음은 마켓플레이스 정책 영역이다.
IoT/펌웨어 주제가 아니라 결제·세션·인가 바인딩이 핵심이다. 프롬프트 인젝션을 핵심 주제로 다루는 논문이 아니라, 서명된 결제 체인이 결정을 묶지 못하는 프로토콜 공백을 다룬다.
레드팀 / 모의해킹 실무 적용
인가된 에이전트 커머스·슈퍼앱 미니앱 결제·위임 결제 점검에서 다음을 분리해서 본다.
관찰: 서명 검증 통과 ≠ 사용자 결정과 일치.
보안 속성: “constraints가 피해를 상한한다”는 제약이 실제로 채워지고, 자격증명 조회가 세션에 묶은 뒤에만 참이다.
실제 영향: 가맹점·툴·검색 결과가 자유 텍스트를 에이전트에 넣을 수 있으면, 유효한 결제 객체가 잘못된 계정·잘못된 카트·잘못된 선택을 실을 수 있다.
미충족 조건: 모델 가드·사용자 입력 필터만 켜 두고 검색 결과·툴 출력을 안 보면 Selection과 가져온 페이지 경로가 남는다.
실무 적용 순서(인가 범위 안)
- 사람-존재 / 사람-부재 에이전트가 constraints를 채우는지 설정을 읽는다.
- 결제수단 조회 API가 세션·로그인 매핑만 받는지, 에이전트가 고른 식별자를 그대로 받는지 확인한다.
- 카트 서명 전에 표시 스냅샷(상품 ID, 단가, 통화, 수량 상한, 정산 DID)이 커밋되는지 본다.
- 검색/툴로 들어온 텍스트와 사용자가 붙인 텍스트에 같은 필터가 적용되는지 비교한다.
- Intent에 기계 가독 예산이 없으면 고가 선택이 사용자 확인 없이 끝나는지 본다.
실제 점검 시 추가할 체크리스트
- [ ] Intent / Cart / Payment가 각각 서명되는가. 사람-존재 경로의 constraints가 비어 있지 않은가.
- [ ] 자격증명 조회가 카트 생성 전인가. 세션 ID만으로 사용자를 해석하는가. 에이전트·가맹점이 계정 식별자를 보거나 넣지 못하는가.
- [ ] 조회 토큰이 카트 해시·상환 가맹점 DID·nonce·만료에 묶이고 1회용인가.
- [ ] 표시 스냅샷과 카트 라인이 상품 ID·단가·통화·수량에서 일치하는가. 총액이 라인 합과 같은가.
- [ ] 세금·배송·쿠폰이 별도 표시/승인 라인으로만 들어가는가.
- [ ] 정산 수취인이 그 상품을 보여 준 스토어프론트 DID인가.
- [ ] 동일 승인 아래 두 번째 서명 카트, 과도한 유효 기간, 재사용 Mandate가 거절되는가.
- [ ] 사람-부재 경로의 allowed-payees / amount-range가 리다이렉트·인플레이션을 실제로 거절하는가.
- [ ] Intent에 예산이 없으면 더 비싼 동급 상품 선택이 확인을 요구하는가. 예산이 있으면 그 범위 안은 조용히 통과하는가.
- [ ] 사용자 입력 필터와 검색/툴 산출물 필터가 같은가. 붙여넣기만 막고 가져온 문서는 통과하지 않는가.
- [ ] 에이전트가 가맹점 재고·단종·후속 모델 주장을 가맹점 원 데이터가 아닌 독립 조회로 확인하는가.
- [ ] 부가 상품이 표시되지 않은 채 총액만 맞으면 통과하지 않는가.
- [ ] 멀티테넌트 지갑에서 다른 테넌트 alias가 도구 로그에 남는지 합성 계정으로만 확인하는가.
- [ ] A2A 에이전트 카드·툴 스키마가 조회 인자를 자유롭게 받지 않는가.
공개된 PoC / Tool / Artifact
- 논문 / PDF: https://arxiv.org/abs/2609.11757 , https://arxiv.org/pdf/2609.11757.pdf
- AP2 명세 v0.2.0: https://ap2-protocol.org/ap2/specification/ (태그 v0.2.0, commit b4587ac1)
- A-VIP 방어·하네스·DDFC 기계검증: https://github.com/yedidel/avip_defense (Apache-2.0)
- AP2-WhisperBench: https://huggingface.co/datasets/anonymos-2321135/ap2-whisperbench (CC-BY-4.0)
- 적응형 패러프레이즈 문자열은 공개 창이 닫힌 뒤에만 같은 조건으로 공개한다고 적혀 있다. 이 노트는 그 문자열을 재수록하지 않는다.
- 라이브 가맹점·라이브 지갑을 겨냥한 아티팩트는 없다고 저자가 명시한다.
결론
AP2는 거래에 서명하지 결정에 서명하지 않는다. 가맹점 텍스트가 그 공백을 채우면, 유효한 Mandate가 잘못된 계정·잘못된 카트·잘못된 선택을 실을 수 있다. 모델 교체로는 살 수 없는 속성이고, 프로토콜 소유자가 통제하는 지점은 자격증명 조회 바인딩, 표시-카트 산술, 예산 없는 고가 선택 확인이다. 인가된 점검에서는 “서명 통과”를 성공 조건으로 두지 말고, 세션에 묶인 조회·표시 스냅샷·가져온 콘텐츠 필터·기계 가독 예산을 따로 확인해야 한다.
댓글