
GhostApproval: 심볼릭 링크가 어떻게 AI 에이전트의 허용된 폴더를 컴퓨터 전체에 대한 접근 권한으로 바꾸는가: Claude
요약
Wiz Research가 AI 에이전트의 권한 승인 메커니즘을 악용하는 'GhostApproval' 취약점 클래스를 발표했습니다. 심볼릭 링크를 이용해 승인된 폴더 외부의 민감한 파일에 접근할 수 있는 보안 결함을 다룹니다.
핵심 포인트
- 심볼릭 링크를 통해 승인된 폴더 외부의 파일(예: SSH 키)에 접근 가능
- 승인 인터페이스가 실제 경로가 아닌 링크 경로를 표시하여 사용자 기만
- Claude Code, Cursor, Amazon Q 등 주요 AI 코딩 도구 영향권
- 도구 업데이트 및 프로젝트 내 심볼릭 링크 존재 여부 확인 권장
당신은 단 한 번 "이 폴더에서의 작업 허용"을 클릭했을 뿐이지만, 에이전트는 해당 폴더뿐만 아니라 그 이상의 권한을 얻게 되었습니다. 프로젝트 내부에는 겉보기에 무해해 보이는 notes.txt 파일이 있습니다. 하지만 실제로는 이는 ~/.ssh/id_rsa에 대한 심볼릭 링크 (symbolic link)입니다. 에이전트가 notes.txt를 열면, 승인 창에는 프로젝트 내부의 익숙한 경로가 표시됩니다. 당신이 읽기 승인을 하면, 개인 키 (private key)가 모델의 컨텍스트 (context)로 전송됩니다. 당신은 화면에 표시된 경로를 보았지만, 에이전트는 그 경로가 가리키는 실제 파일을 읽은 것입니다.
Wiz Research는 바로 이 격차를 GhostApproval이라고 명명하고 2026년 7월 8일에 발표했습니다.
1분 핵심 요약
- 2026년 7월 8일, Wiz Research는 6개 공급업체와의 조율된 공개(coordinated disclosure)를 거쳐 GhostApproval 취약점 클래스를 공개했습니다 (출처: Wiz Research, 2026-07-08).
- 핵심: 신뢰할 수 있는 워크스페이스 (workspace) 내부의 심볼릭 링크 (symbolic link)가 외부의 파일을 가리킬 수 있으며, 승인 인터페이스는 민감한 파일로 연결되는 실제 경로가 아닌 링크의 경로를 보여줍니다 (출처: Wiz Research).
- 점검 대상에는 Amazon Q, Claude Code, Augment, Cursor, Google Antigravity 및 Windsurf가 포함되었습니다 (출처: Wiz Research; ITPro 확인, 2026-07-09).
- Amazon은 이 문제를 CVE-2026-12958로, Cursor는 CVE-2026-50549로 수정했습니다. 공급업체마다 상태와 해석이 다르므로 모든 제품이 동일하게 취약했다고 단정할 수는 없습니다 (출처: Wiz Research).
- Wiz는 이 기술이 실제 공격에서 확인된 사례에 대해 보고하지 않았습니다 (출처: Wiz Research). 이는 실제 침해 사고 보고가 아닌 연구자들의 발견입니다.
만약 Claude Code 에이전트와 작업 폴더 보안에 관한 질문으로 이곳에 오셨다면, 짧은 결론을 드립니다: 도구를 수정 버전으로 업데이트하고, 에이전트에게 권한을 주기 전에 프로젝트 내에 심볼릭 링크 (symlink)가 있는지 확인하며, 승인 창에 표시되는 경로를 절대적인 진실로 신뢰하지 마세요.
이러한 제어 체계를 구축하는 동안, 동일한 요청에 대해 서로 다른 모델들의 동작을 빠르게 비교해 보는 것이 유용합니다. 하나의 API를 통해 제공업체 간을 번거롭게 이동하지 않고도 이를 수행할 수 있습니다 (provod.ai).
2026년 7월 8일에 정확히 무슨 일이 일어났는가
발견 사항을 둘러싸고 이미 많은 부정확한 정보가 쌓여 있으므로, 용어를 정리해 보겠습니다.
Wiz Research는 단일 제품의 개별적인 취약점을 설명한 것이 아니라, 코드 어시스턴트 (code assistant)의 신뢰 모델에 존재하는 문제 클래스를 설명했습니다. 일반적인 메커니즘은 다음과 같습니다: 도구가 사용자가 신뢰할 수 있다고 표시한 작업 폴더 내에서 에이전트 (agent)가 읽고 쓸 수 있도록 허용합니다. 신뢰의 경계는 이 폴더를 기준으로 설정됩니다. 하지만 파일 시스템 (file system)은 심볼릭 링크 (symbolic links)를 통해 이러한 경계를 뚫을 수 있으며, 링크의 경로가 아닌 링크가 실제로 가리키는 대상 경로를 확인하지 않고 "파일이 허용된 폴더 내에 있는가?"를 검사하면 쉽게 실패하게 됩니다.
검사는 Amazon Q, Claude Code, Augment, Cursor, Google Antigravity, Windsurf 등 6개 제품을 대상으로 수행되었습니다 (출처: Wiz Research; ITPro, 2026-07-09에서도 동일한 목록 나열). 연구진이 덧붙인 중요한 유의사항은 다음과 같습니다: 제공업체마다 상태와 해석이 다릅니다. 공개된 데이터에 따르면 Amazon은 CVE-2026-12958 식별자를 가진 수정 사항을 출시했으며, Cursor는 CVE-2026-50549를 출시했습니다. 나머지 참여자들에 대해서는 출처에 공개적인 CVE가 명시되지 않았으므로, 6개 제품 모두가 동일한 취약점을 가졌다고 말하기보다는 각기 다른 대응을 하고 있다고 말하는 것이 정확합니다.
또 다른 정직한 경계는 다음과 같습니다: Wiz는 실제 공격에서 확인된 악용 사례(exploitation)가 있다고 주장하지 않았습니다. 이 연구는 취약성 조사 및 공개 조율에 관한 것이지, 피해자가 발생한 사고를 분석하는 것이 아닙니다. 이 차이는 근본적입니다. 에이전트 신뢰 모델에 대한 커뮤니티의 논의는 주의를 기울이라는 신호이지, GhostApproval을 통해 누군가가 이미 해킹당했다는 증거가 아닙니다.
심볼릭 링크가 어떻게 에이전트를 폴더 외부로 유출시키는가
핵심: 신뢰할 수 있어야 하는 것은 경로 문자열이 아니라, 모든 링크가 해석된 후 경로가 실제로 가리키는 inode입니다.
심볼릭 링크 (Symbolic link)는 그 내용이 다른 파일로 향하는 경로인 파일입니다. 링크를 열면 운영체제 (OS)는 조용히 사용자를 목적지로 안내합니다. 만약 검증 단계가 오직 첫 번째 문자열만 확인한다면, 에이전트에게 ./project/notes.txt와 /home/you/.ssh/id_rsa는 동일한 읽기 작업으로 보일 것입니다.
터미널에서의 모습은 다음과 같습니다. 타인의 기기에서 재현할 필요는 없으며, 본인의 기기에서 메커니즘을 이해하기 위한 용도입니다:
# 신뢰할 수 있는 프로젝트 폴더 내부
cd ~/project
ln -s ~/.ssh/id_rsa notes.txt
...
취약점은 승인 검증 단계에 있습니다. 나이브한 (Naive) 검증은 다음과 같이 이루어집니다:
# 위험: 실제 목적지가 아닌 경로 문자열을 비교함
import os
...
os.path.abspath는 심볼릭 링크 (symlink)를 확장하지 않습니다. ~/project/notes.txt라는 문자열은 정직하게 워크스페이스 (workspace) 루트에서 시작하므로, 검증은 True를 반환하지만 실제로는 그 범위를 벗어난 키(key)를 읽게 됩니다.
올바른 검증은 비교하기 전에 링크를 허용(resolve)해야 합니다:
# symlink를 확장한 후 허용된 경로를 비교함
import os
...
Wiz가 설명한 오류의 유형이 바로 이것입니다. 승인 인터페이스는 링크의 경로를 보여줄 뿐, 민감한 파일로 향하는 실제 허용된 경로를 보여주지 못합니다 (출처: Wiz Research). 사용자는 자신이 보고 있는 것에 승인합니다. 하지만 그가 보고 있는 것은 실제로 일어날 일이 아닙니다.

승인 창이 형식적으로는 거짓말을 하지 않음에도 왜 기만적인가
핵심: 승인은 링크에 적힌 내용이 아니라, 허용된 경로에 대해 이루어질 때만 의미가 있습니다.
"에이전트가 이 파일을 읽도록 허용하시겠습니까?"라는 창은 인간이 책임을 떠맡는 지점입니다. GhostApproval은 바로 그 지점을 공격합니다. 형식적으로 인터페이스는 거짓말을 하지 않습니다. 에이전트가 파일에 접근한 경로를 보여주기 때문입니다. 하지만 인간은 그 경로를 "프로젝트 내부의 파일"이라는 약속으로 읽으며, 시스템은 그러한 약속을 한 적이 없습니다.
승인(consent)이 다시 의미를 갖기 위해서는, 파일을 읽기 전에 요청된 경로와 허용된 경로가 서로 다를 경우 두 경로를 모두 보여주어야 합니다. 그렇게 하면 notes.txt -> /home/you/.ssh/id_rsa와 같은 문자열이 즉시 정체를 드러낼 것입니다. 이것이 바로 이번 발견의 핵심(editorial-угол)이 말하는 승인의 경계, 즉 신뢰가 어디까지 미치는지와 행동을 취하기 전에 사용자에게 정확히 무엇을 보여주어야 하는지에 대한 문제입니다.

만약 당신이 직접 어떤 API를 기반으로 에이전트를 구축하고 있다면, 이러한 승인 화면을 위한 실무적인 체크리스트는 다음과 같습니다:
- 어떤 읽기 작업이 이루어지기 전에
realpath/os.path.realpath를 통해 경로를 확인하십시오. - 요청된 경로와 허용된 경로가 다를 경우, 창에 두 경로를 모두 표시하십시오.
- 워크스페이스(workspace) 경계를 벗어나는 것을 명시적인 재확인이 필요한 별도의 이벤트로 간주하십시오.
- 링크 경로가 아닌 실제 허용된 경로를 로그(log)에 기록하십시오. 그렇지 않으면 사고 발생 후 감사(audit)를 해도 아무것도 나타나지 않을 것입니다.
- 심볼릭 링크(symlink)를 통한 외부 읽기를 기본적으로 차단하십시오. 사용자가 매번 눈으로 바꿔치기된 경로를 잡아내도록 요구해서는 안 됩니다.
지금 바로 해야 할 일: 실행 단계
핵심: 도구를 업데이트하고, 프로젝트 내에 외부로 연결되는 링크가 있는지 스캔하며, 타인의 리포지토리(repository)를 맹목적으로 신뢰하지 마십시오.
1단계. 코드 어시스턴트를 업데이트하십시오. Wiz의 데이터에 따르면, 알려진 수정 사항이 있는 제품은 Amazon Q (CVE-2026-12958)와 Cursor (CVE-2026-50549)입니다. 나머지 참여자들에 대해서는 각자의 릴리스 노트(release notes)를 확인하십시오. 벤더(vendor)마다 대응 방식이 다르기 때문에 모든 제품에 적용되는 단일 날짜는 없습니다.
2단계. 에이전트에게 권한을 부여하기 전에, 모든 리포지토리에서 외부로 연결되는 심볼릭 링크(symbolic links)를 찾으십시오:
# 프로젝트 내의 모든 symlink와 실제 연결 대상을 표시
find . -type l -print0 | while IFS= read -r -d '' link; do
target=$(readlink -f -- "$link")
...
외부로 표시된 모든 것은 에이전트가 "내부" 파일로 읽게 될 대상입니다.
단계 3. 클론(clone)한 타인의 리포지토리를 신뢰할 수 없는 입력값으로 취급하세요. ~/.ssh/id_rsa, ~/.aws/credentials 또는 인접한 프로젝트의 .env에 대한 심볼릭 링크가 당신이 에이전트에서 해당 리포지토리를 열기도 전에 이미 그 안에 포함되어 있을 수 있습니다.
단계 4. 진정으로 민감한 비밀 정보(secrets)는 단순히 "프로젝트 내에 두지 않는 것"을 넘어, 가능하다면 작업 폴더 및 사용자 홈 디렉토리(user home directory)가 닿지 않는 곳에 보관하세요.
단계 5. 승인 화면을 허용된 경로의 표시로 읽으세요. 만약 도구가 링크가 어디로 연결되는지 보여주지 않는다면, 그것을 위험이 없다는 뜻이 아니라 정보가 부족한 상태로 간주해야 합니다.
결정 테이블: 접근을 신뢰할 것인가 말 것인가
| 상황 | 외부로 향하는 심볼릭 링크 존재 여부 | 조치 사항 |
|---|---|---|
| 본인의 프로젝트이며, 모든 파일을 직접 생성함 | 아니요 | 일반적인 에이전트 접근 허용 |
| ... | ... | ... |
이것이 모델의 선택 및 비교와 어떤 관련이 있는가
핵심: 취약한 부분은 언어 모델(LLM) 자체가 아니라, 도구의 승인 계층(consent layer)과 파일 접근 계층입니다. 하지만 모델의 선택은 에이전트가 어떻게 행동하는지에 여전히 영향을 미칩니다.
여기서 두 가지를 구분해야 합니다. GhostApproval은 도구의 래퍼(wrapper) 문제입니다. 즉, 도구가 경로를 어떻게 확인하고 승인 화면을 어떻게 그리는지의 문제입니다. 모델을 바꾼다고 해서 이 버그가 고쳐지지는 않습니다. 이 문제는 도구를 업데이트하고 realpath를 올바르게 검증함으로써 해결됩니다.
모델에 실제로 의존하는 부분은 접근 권한이 부여된 후의 에이전트 행동입니다. 즉, 파일을 왜 읽어야 하는지 얼마나 정확하게 설명하는지, 키(key)로 연결되는 의심스러운 notes.txt에 어떻게 반응하는지, 사용자에게 경고를 줄 가능성이 얼마나 높은지 등입니다. 이를 공정하게 평가하려면 동일한 위협 시나리오를 여러 모델 제품군(model families)에 실행해 보고 응답을 나란히 비교해 보는 것이 유용합니다.
이 지점에서 러시아로부터 실용적인 가교가 등장합니다. provod.ai는 Claude, GPT, Gemini, DeepSeek, Qwen을 하나의 채팅창에 모아 OpenAI 및 Anthropic SDK와 호환되는 단일 API를 제공합니다. 즉, 키(key)와 base_url만 바꾸면 나머지 코드는 동일하게 유지됩니다. 이는 별도의 구독이나 VPN 없이도, 어떤 모델이 경로 변조를 더 잘 감지하는지 빠르게 파악해야 하는 모델 제품군(model families) 간의 비교 및 라우팅(routing) 작업에 매우 유용합니다. 결제는 러시아 카드를 통한 루블화 결제, SBP(Faster Payments System) 또는 계좌 이체가 가능하며, 모든 모델에 대해 하나의 잔액을 사용합니다. 법인의 경우 계약서, 인보이스 및 증빙 서류 발급이 가능합니다 (provod.ai).
이러한 호환 API로 전환하는 최소한의 예시는 다음과 같습니다. 비밀은 코드 내부가 아닌 환경 변수(environment variable)에 두는 것입니다:
from openai import OpenAI
client = OpenAI(
...
model을 다른 제품군으로 변경하며 동일한 요청을 반복하고, 누가 경고를 울리는지 비교해 보세요. 이 방법 자체가 접근 권한 버그를 해결해 주는 것은 아닙니다. 버그를 해결하려면 도구를 업데이트해야 합니다. 하지만 적어도 경고를 해줄 수 있는 모델을 선택하는 데는 도움이 됩니다.

흔한 실수와 디버깅 방법
핵심: 대부분의 실패 사례는 심볼릭 링크(symlink)를 조용히 허용하거나, 로그에 잘못된 경로가 기록되는 경우입니다.
사용자가 직접 에이전트를 구축하거나 내장할 때 발생하는 전형적인 실수들을 살펴보겠습니다. 여기에는 파일 및 모델 호출이 화면 앞의 사람 없이 이루어지는 n8n과 같은 플랫폼의 자동화 환경 내에서의 사례도 포함됩니다.
realpath대신abspath를 통한 검증. 가장 흔한 사례입니다. 문자열 검증은 통과하지만, 링크는 살아있습니다. 위에서 언급한 것처럼os.path.realpath와commonpath로 교체하여 해결할 수 있습니다.- 구분자 없는 접두사(Prefix) 검증.
startswith("/work")는/work-evil을 통과시켜 버립니다. 항상 경로 구성 요소(path components) 단위로 비교하십시오. - 자동화 환경에서의 인간 없는 승인. n8n이나 이와 유사한 파이프라인에서는 승인 화면이 아예 꺼져 있는 경우가 많습니다. 즉, 보호 조치는 인터페이스가 아니라 읽기 전 코드 단계에서 이루어져야 합니다. 신뢰할 수 없는 리포지토리(repository)에서의 읽기 자동 승인(Auto-approval)은 GhostApproval 시나리오로 가는 직행로입니다.
- 로그에 링크 경로가 기록됨. 사고 발생 후
notes.txt를 보게 되더라도 키(key)가 유출되었다는 사실을 이해하지 못할 수 있습니다. 허용된 경로를 로그로 남기십시오. - TOCTOU 레이스 컨디션 (TOCTOU race). 경로를 확인한 후 파일을 열 때, 그 두 단계 사이에 링크가 교체될 수 있습니다. 가능한 경우, 경로를 두 번 확인하지 말고 파일 디스크립터(descriptor)를 열어 이를 검증하십시오.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기