ANSI Escape Sequence Injection(AESI)은 ANSI 터미널 제어문자를 이용해 사람의 화면에는 숨겨지거나 지워지는 텍스트를 AI 모델 입력에는 그대로 남기는 공격이다. MCP 서버가 외부 페이지, 사용자 입력, 저장된 레코드를 도구 결과로 반환할 때 이 제어문자가 모델이 읽는 필드까지 살아남으면 프롬프트 인젝션으로 이어진다.
왜 위험한가
ANSI escape sequence는 색상 변경, 커서 이동, 화면 지우기, 텍스트 숨김 같은 터미널 제어를 위해 만들어졌다. 사람은 렌더링된 결과만 보지만, 모델은 원본 바이트를 읽는다. 그래서 사람에게는 빈 줄이나 정상 로그처럼 보이는 출력 안에 “다음 도구를 호출하라”, “이 결과를 무시하라” 같은 지시가 숨어 있을 수 있다.
공격 유형
| 유형 | 흐름 | 위험 |
|---|---|---|
| Direct-fetch AESI | MCP fetch 도구가 공격자 URL을 읽고 결과를 모델 필드에 전달 | 외부 문서 요약, 웹 읽기 도구에서 즉시 발화 |
| Stored AESI | 쓰기 엔드포인트로 저장한 payload가 나중에 MCP read 도구로 재노출 | 지속성, 다른 사용자·세션으로 확산 |
중요한 기준은 “model-consumable field”다. MCP 응답 전체가 아니라 result.content[].text, result.contents[].text, prompt message text처럼 실제 모델 컨텍스트에 들어가는 필드에 payload가 도달해야 취약하다.
DAST 탐지 방식
Bright Security 글은 AESI 탐지에 동적 애플리케이션 보안 테스트(DAST)가 적합하다고 설명한다. 소스 코드를 보는 것만으로는 제어문자가 실제 서버 처리 과정에서 제거되는지, JSON 문자열 안에 감싸져 살아남는지, 저장 후 어떤 read surface로 되돌아오는지 알기 어렵기 때문이다.
탐지기는 다음 신호를 함께 확인한다.
- raw response bytes 안의 ANSI escape byte
- 고정된 악성 instruction phrase
- payload별 unique trigger marker
- 모델이 실제 읽는 JSON path
- 문자열화된 JSON 내부까지 재귀 검사
이 세 신호가 같은 model-consumable field에 함께 살아남을 때만 취약점으로 보고하면 false positive를 줄일 수 있다.
방어 원칙
| 방어 | 설명 |
|---|---|
| 제어문자 제거 | 모델 필드로 넣기 전 ANSI control bytes를 제거 |
| 입력 검증 | URL fetch, note, comment, record write 입력을 신뢰하지 않음 |
| 저장 데이터 재검사 | 쓰기 시점뿐 아니라 읽기 시점에도 sanitize |
| model field 경계 정의 | 어떤 MCP 응답 필드가 모델에 들어가는지 명시 |
| 지속 스캔 | MCP tools, resources, prompts를 CI/DAST에서 반복 검사 |
언제 특히 조심해야 하나
- MCP 서버가 URL을 받아 웹페이지나 파일을 fetch한다.
- 지식베이스, 노트, 이슈, 댓글처럼 저장된 텍스트를 나중에 에이전트가 읽는다.
- 터미널 로그, ANSI 컬러 출력, CLI 결과를 그대로 모델에게 전달한다.
- 사람이 승인하는 human-in-the-loop UI가 렌더링 결과만 보여준다.
관련 문서
- mcp — 에이전트와 외부 시스템을 연결하는 표준 프로토콜
- ai-agent-security-tips-prompt-injection-3-hops — 3홉 프롬프트 인젝션 데이터 유출
- context-bombing — 방어자가 프롬프트 인젝션을 역이용하는 기법
- secure-mcp-tunnel — 로컬·프라이빗 MCP 서버 연결 터널
참고 자료
- Detecting ANSI Escape Sequence Injection in MCP Servers with DAST — Bright Security Research (2026-07-24)