요약
이 논문이 재현한 취약점 유형은 에이전트 제품 세 곳의 테스트된 구성에서 확인됐습니다. 사람이 한 동작을 승인해도 시스템은 다른 동작을 실행할 수 있었습니다. 승인자도 같고 클릭도 같습니다. 논문은 이 현상을 루프재킹(Loopjacking)이라고 부릅니다. 이 문제는 승인 버튼을 누른 사람이 누구인지와 무관합니다. 문제는 실행된 것이 화면에 보여준 것과 여전히 같은지 확인하는 장치가 없었다는 데 있습니다.
논문이 발견한 것
Kumar가 2026년 9월 발표한 논문 "Loopjacking: Hijacking Human-in-the-Loop Approval"(arXiv:2609.21081)은 에이전트 제품 세 곳의 테스트된 구성에서 같은 취약점 유형을 재현했습니다. 사람이 한 동작을 승인했는데도 시스템은 다른 동작을 실행했습니다. 승인자도 클릭도 같았습니다. 승인만으로는 통제가 부족하다는 점은 이미 다른 사고에서도 드러났습니다. 루프재킹은 바로 그 공백이 생기는 구체적이고 재현 가능한 메커니즘입니다. 논문은 사람이 검토한 동작과 이후 인가되거나 실행되는 동작이 같을 때에만 승인이 보안 경계로서 의미를 가진다고 설명합니다.
승인한 내용이 바뀌는 두 경로
논문은 이 문제가 생기는 경로를 두 가지로 나눕니다. 한쪽은 검토 화면이 요청 전체를 보여주지 못하는 경우이고, 다른 한쪽은 승인 뒤 대기 중인 상태가 바뀌는 경우입니다.
표현 기반 루프재킹(representation-based Loopjacking): "The complete request or execution context contains B before the decision, but the product displays, canonicalizes, or checks a materially incomplete A."(결정이 내려지기 전, 완전한 요청이나 실행 컨텍스트에는 이미 B가 들어 있지만 제품은 실질적으로 불완전한 A만 보여주거나 정규화하거나 검사한다.) 위험한 동작은 이미 요청 안에 들어 있고, 검토 화면만 그 전체를 보여주지 않습니다.
승인 후 상태 치환(post-approval state-substitution): "The human sees and approves exact A. Before the approval is consumed, an actor changes pending task, thread, session, or continuation state to B."(사람은 정확히 A를 보고 승인한다. 승인이 소비되기 전, 어떤 행위자가 보류된 작업이나 스레드, 세션, 연속 상태를 B로 바꾼다.) 검토자가 보는 화면은 실제와 다르지 않습니다. 이후 승인이 소비되기 전에 그 내용이 B로 바뀝니다.
논문이 재현한 것
가상의 구성만 다룬 연구는 아닙니다. 저자는 이름과 버전이 명시된 실제 제품에서 두 공격 형태를 모두 직접 재현했습니다.
- Agno AgentOS: 승인 후 상태 치환을 3.0.9까지 일곱 개 릴리스에 걸쳐 재현했습니다. 논문의 조사 시점까지 수정된 릴리스는 확인되지 않았습니다.
- LangGraph Agent Server: 0.7.5부터 0.14.0까지 열두 개 버전에서 재현했습니다. 승인 권한이 없는 사용자도 보류된 스레드를 수정할 수 있게 둔 특정 인메모리 구성에서만 재현된 결과입니다. 제품이 지원하는 정책으로 그 수정을 거부하자 공격이 막혔습니다. 논문은 기본 구성이나 Postgres 기반 프로덕션 배포에 대해서는 어떤 주장도 하지 않습니다.
- OpenClaw: 표현 불일치를 v2026.2.23에서 재현했고, 2026.2.24에서 수정됐습니다.
OpenClaw의 불일치는 이미 공개된 취약점이었습니다(CVE-2026-32052, 2026.2.24에서 수정). Agno와 LangGraph 사례에는 CVE가 없습니다. 저자가 관리하는 증거 저장소도 논문의 증거 수집 마감 시점인 2026-09-10 기준으로, 두 제품 모두 벤더가 수정한 릴리스를 아직 기록하지 않았습니다.
치환을 막아낸 시스템도 하나 있습니다. OpenAI Agents SDK(v0.22.0, v0.22.2)입니다. 논문은 이 제품을 승인 후 상태 치환에 대해서만 검증했습니다. 승인 후 직렬화된 보류 호출을 바꾸자 재개(resume)가 실패했고 아무것도 실행되지 않았습니다. 호출 단위로 이뤄지는 일반적인 승인이 정확한 호출 내역을 정규 기록으로 남기기 때문입니다. 이는 설계상의 선택이지 에이전트 오케스트레이션이라면 반드시 갖는 성질이 아닙니다. 논문은 이 결과를 대조군(negative control)으로 규정하며, SDK를 감싸는 애플리케이션 쪽 승인 구현이 모두 안전하다는 뜻으로 제시하지 않습니다. 항상 승인하도록 고정된 정책이나, 신뢰되는 모든 정규 필드를 위조할 수 있는 공격자는 다루지 않았습니다. 표현 기반 변형에 대해서는 아예 검증하지 않았습니다.
이 논문은 스스로 범위를 다음과 같이 제한합니다.
- 연구자 한 명이 진행했습니다.
- 제품 표본은 무작위가 아니라 의도적으로 골랐습니다.
- 독립적인 재현 검증은 거치지 않았습니다.
- 어떤 결과에도 자체 CVSS나 심각도 점수를 붙이지 않았습니다(OpenClaw의 권고문 자체는 medium 등급입니다).
따라서 이 결과만으로 생태계 전체에서 얼마나 흔한지 판단할 수는 없습니다. 논문도 발생 빈도를 추정하지 않습니다. 다만 메커니즘 자체는 실제 코드와 실제 버전에서 직접 재현됐습니다.
20만 원을 승인했는데 2,000만 원이 송금된 경우
논문이 직접 든 예시는 이렇습니다. 관리자는 승인된 거래처에 20만 원을 송금하는 요청을 검토합니다. 승인이 실제로 사용되기 전, 보류된 인자가 공격자가 지정한 수취인에게 2,000만 원을 송금하도록 바뀝니다. 금액은 원래의 100배입니다.
참고: 논문 원문은 통화를 특정하지 않고 20과 2,000을 예시로 듭니다. 여기서는 이해를 돕기 위해 원화로 풀어 썼습니다.
에이전트의 동작을 승인하는 사람이라면 이 구조를 눈여겨봐야 합니다. 승인자는 작고 그럴듯한 요청을 보고 승인했습니다. 그런데 실행된 것은 완전히 다른 요청이었고, 그 요청을 승인한 기록은 실행된 내용과 다시 대조되지 않았습니다.
채널 분리와는 다른 공백인 이유
관련은 있지만 다른 실패 유형 하나를 구분해 둘 필요가 있습니다. **채널 분리(channel separation)**는 에이전트의 CLI나 API 토큰 같은 실행 채널을 승인 채널 목록에서 제외합니다. 여기서 다루는 것은 누가, 어디서 승인하느냐입니다. 에이전트는 요청을 보낸 채널로 그 요청을 스스로 승인할 수 없습니다.
루프재킹은 무엇을 승인했는지에 관한 문제입니다. 사람이 올바른 승인 채널에서 요청을 검토했더라도, 실제 실행되는 동작은 화면에서 본 내용과 달라질 수 있습니다. 채널 분리는 요청자가 자기 요청을 직접 승인할 수 없는 경로로 승인이 들어왔는지를 확인합니다. 실행 직전의 동작이 승인 화면의 내용과 같은지는 별도로 확인해야 합니다.
실제로 막는 방법
논문이 제안하는 완화책은 특별하지 않습니다.
- 인자, 대상 리소스, 주체, 범위까지 동작 식별 정보 전체를 하나의 완전한 정규 서술자(canonical descriptor)에 묶어 두는 정규 승인 기록
- 검토 시점뿐 아니라 마지막 인가 지점인 사용 시점에도, 실행하려는 동작을 재구성해 그 서술자와 대조하는 검사
- 또는, 신뢰되지 않은 행위자가 보류된 승인 상태를 수정하지 못하게 막는 인가 정책
검증 대상이었던 Agno 릴리스와 LangGraph 구성에서는, 사용 시점의 동작을 승인된 내용과 대조하는 절차가 아예 없었습니다. OpenClaw는 2026.2.24에서 전체 셸 인자 벡터를 대조하는 검사를 추가했습니다. 다만 이후 공개된 별도 권고문(GHSA-2j8v-hwgc-x698)은 관련된 셸 래퍼 결함을 2026.5.18에 수정했다고 밝히고 있어, 그 사이 버전을 쓰는 배포는 앞선 수정만으로 보호되지 않습니다. 논문의 설명대로라면, OpenAI Agents SDK의 대조군 결과를 성립시킨 이 대조 절차가 나머지 두 사례에는 없었습니다.
물어야 할 질문
이체, 삭제, 권한 있는 명령처럼 중대한 작업에 human-in-the-loop 승인을 쓰고 있다면, 이 논문을 읽고 나면 승인 게이트에 던질 구체적인 질문이 하나 남습니다. 시스템은 실행되는 순간에 그 동작이 검토된 내용과 일치하는지 확인합니까? 아니면 승인 권한이 있는 누군가가 승인 버튼을 눌렀다는 것만 확인합니까?
두 확인은 서로 다른 보장입니다. 루프재킹은 시스템이 두 번째 확인만 만들어 놓고 그것이 첫 번째 확인까지 대신한다고 가정할 때 일어납니다.
AI 에이전트 거버넌스에서는 두 질문 모두에 답해야 합니다.
