강좌 강좌
제로 클릭 원격 코드 실행 입문: 피해자 조작 없이 코드가 실행되는 조건
'제로 클릭'은 공격자가 뛰어나다는 뜻이 아니라, 사용자가 아무것도 누르지 않아도 코드가 들어오는 통로가 열려 있다는 뜻입니다. AI 코딩 도구에서 보고된 '플러그인4쉘' 사례를 처음부터 끝까지 따라가며 이 상태가 성립하는 조건과 한계를 봅니다.
한 문장으로 이해하기
제로 클릭 원격 코드 실행(Zero-Click Remote Code Execution)은 보안 소식에서 자주 보이는 용어입니다. 이 강좌에서 다루는 ‘플러그인4쉘’ 사례에서는 사용자의 추가 확인이나 클릭 없이 외부 저장소에서 바뀐 플러그인 코드가 사용자 환경에서 실행될 수 있었습니다. 즉 ‘제로 클릭’이라는 말은 그 코드가 들어오는 과정에 사용자의 확인이나 클릭이 끼어들지 않는다는 상황을 가리킵니다.
이 강좌의 목표는 세 가지입니다. 첫째, 이 사례에서 제로 클릭이라는 말이 무엇을 가리키는지 구분하기. 둘째, 자동 업데이트 통로와 검증 빈틈이 겹치는 과정을 단계로 설명하기. 셋째, 이 결함이 성립하는 조건과 성립하지 않는 조건, 확인되지 않은 부분을 가려내기. 사전지식은 많이 필요하지 않습니다. 프로그램을 설치하고 업데이트해 본 경험, 그리고 소스 코드를 보관하는 ‘저장소’라는 공간이 있다는 정도만 알면 충분합니다.
왜 필요한가
보안 안내는 흔히 “의심스러운 링크를 누르지 마세요"라고 말합니다. 이 조언은 사용자의 클릭이 출발점이라는 전제를 깔고 있습니다. 플러그인4쉘은 그 전제가 적용되지 않는 경우를 보여 줍니다. 그래서 무엇을 점검해야 하는지가 달라집니다. 사용자의 습관이 아니라, 코드가 자동으로 들어오는 통로와 그 통로에서 코드를 검증하는 지점을 봐야 합니다.
개념을 구분해 두면 기술 뉴스를 읽는 기준이 생깁니다. 결함 설명을 읽을 때 ‘사용자가 무엇을 해야 성립하는가’를 먼저 확인하면, 그 결함에 사용자 조작이 필요한지 스스로 판단할 수 있습니다.
어떻게 이루어지는가
이 사례에서 제로 클릭이 성립하려면 세 가지가 맞아야 합니다. 자동으로 코드를 받아오는 통로, 받은 코드를 검증하는 절차의 빈틈, 그리고 그 코드가 실행될 권한입니다. 보안 업체 에어가 공개한 ‘플러그인4쉘(Plugin4Shell)‘은 이 조건이 AI 코딩 도구의 확장 프로그램(플러그인) 설치 과정에서 어떻게 맞물릴 수 있는지 보여 줍니다.
- 사용자가 AI 코딩 도구에 기능을 더하는 플러그인을 마켓플레이스에서 설치합니다.
- 마켓플레이스는 안전을 위해 그 플러그인을 검토를 마친 한 버전에 고정합니다. 고정에 쓰는 값이 커밋 해시로, 코드의 특정 시점 스냅샷을 식별하는 긴 문자열입니다.
- 그런데 도구가 코드를 받아온 뒤 실제로 받은 코드와 그 해시가 일치하는지 확인하지 않으면, 고정과 다른 코드가 설치될 수 있습니다.
- 커밋 해시처럼 보이는 브랜치 이름을 허용하는 저장소라면, 저장소 관리자가 그런 이름의 브랜치를 만들 수 있습니다. 브랜치는 저장소 안의 이름 붙은 코드 줄기이며, 관리자가 가리키는 코드를 바꿀 수 있습니다.
- 그러면 도구는 고정된 버전이라고 표시하면서 실제로는 다른 코드를 설치합니다. 이렇게 버전 고정이 우회됩니다.
- 배경 자동 업데이트가 켜져 있으면 이미 설치된 플러그인이 사용자 확인 없이 교체될 수 있습니다. 클릭이 필요 없는 지점이 바로 여기입니다.
- 교체된 코드는 사용자가 도구에 준 것과 같은 접근 권한으로 실행되므로, 에어의 설명에 따르면 사용자의 파일, 저장된 인증 정보, 로그인 가능한 시스템에 접근할 수 있습니다.
네 도구가 모두 똑같은 방식으로 뚫린다고 단정할 수는 없습니다. 에어는 클로드 코드, 코덱스, 깃허브 코파일럿, 제미나이 CLI에서 플러그인4쉘을 발견했다고 밝혔지만, 제미나이 CLI에는 기본 브랜치 이름을 FETCH_HEAD로 지정하는 별도 방식이 제시됐습니다.
하나의 예시로 따라가기
위 흐름을 연구 과정에 비추어 이어 보겠습니다. 에어는 2026년 5월 네 에이전트를 대상으로 시험 공격을 구현하고 6월에 업체들에 알렸다고 밝혔습니다. 즉 아래 흐름은 연구진이 통제된 환경에서 구현한 시험 공격이며, 2026년 9월 18일 기준으로 실제 공격에 사용됐다는 징후는 확인되지 않았습니다.
흐름은 이렇습니다. 사용자가 플러그인을 설치하고, 그 플러그인은 검토된 커밋 해시에 고정됩니다. 해시 모양 브랜치 이름이 허용되는 저장소에서 관리자가 그 이름의 브랜치를 만들어 다른 코드를 가리키게 합니다. 도구는 해시가 맞는지 확인하지 않으므로 바뀐 코드를 받아 설치합니다. 배경 자동 업데이트가 켜져 있으면 이 교체에 사용자의 확인이 끼어들지 않습니다. 화면에는 여전히 고정된 버전이 표시되고, 바뀐 코드는 사용자가 도구에 준 권한으로 실행됩니다. 여기까지가 이 사례에서 사용자 조작 없이 바뀐 코드가 실행되는 경로입니다.
대응은 도구마다 달랐습니다. The Hacker News 보도에 따르면 오픈AI의 수정은 코덱스 0.146.0에 포함됐고, 클로드 코드는 2.1.179에서 수정됐다는 에어의 설명이 실렸습니다. 같은 보도의 2026년 9월 18일 확인 시점에는 깃허브 코파일럿용 수정이 없었고, 제미나이 CLI의 해당 결함도 수정되지 않을 것이라는 에어의 설명이 함께 실렸습니다. 또한 버전 고정 검사가 사용자 기기의 에이전트에서 수행되므로, 수정은 마켓플레이스가 아니라 에이전트 쪽에 반영되어야 합니다.
언제 쓰고 언제 쓰지 않는가
제로 클릭이라는 이름이 ‘어디서나 통한다’는 뜻은 아닙니다. 해시 모양 브랜치 이름을 이용하는 방식은 그런 이름을 허용하는 저장소에서만 성립합니다. 깃허브는 커밋 해시처럼 보이는 브랜치나 태그 이름을 허용하지 않으므로, 깃허브 저장소에는 이 브랜치 이름 방식이 적용되지 않습니다. 다만 제미나이 CLI의 FETCH_HEAD 방식은 별도이며, 깃허브의 해시 모양 이름 제한이 이를 막는지는 확립되지 않았습니다. 에어는 커밋 해시처럼 보이는 이름을 허용하는 비트버킷이나 자체 깃 서버에서는 이 방식이 성립할 수 있다고 설명했습니다.
자동 업데이트에도 조건이 있습니다. 출처가 확인한 범위에서 기본 제공 마켓플레이스는 깃허브에 있었고, 외부 마켓플레이스의 자동 업데이트는 꺼져 있거나 선택 사항이었습니다. 따라서 기본 마켓플레이스만 쓰는 경우에는 출처가 설명한 해시 모양 브랜치 이름 방식의 조건이 성립하지 않습니다.
확인되지 않은 부분도 함께 봐야 합니다. 2026년 9월 18일 기준으로 이 결함의 CVE 식별 번호와 네 개발사의 보안 권고문은 확인되지 않았습니다. 에이전트를 업데이트하면 이미 교체된 플러그인이 제거되는지, 아니면 이후의 교체만 차단되는지도 출처에서 확인되지 않습니다. 이처럼 ‘통하는 조건’, ‘통하지 않는 조건’, ‘아직 모르는 부분’을 나눠서 읽는 것이 과장과 안심을 모두 피하는 방법입니다.
핵심 정리와 확인문제
정리하면, 플러그인4쉘 사례의 핵심은 플러그인을 자동으로 받아오는 통로와 받은 코드의 검증이 빠진 지점이 겹쳐 사용자 조작 없이 바뀐 코드가 실행될 수 있었다는 점이고, 통하는 범위는 저장소 규칙과 설정에 따라 좁아집니다. 새로운 결함 소식을 읽을 때는 ‘무엇이 자동으로 들어오는가’와 ‘그것을 누가 어디서 검증하는가’를 먼저 찾아보면 됩니다.
- 플러그인4쉘 사례에서 ‘제로 클릭’은 구체적으로 어떤 상태를 가리킵니까?
- 이 사례에서 버전 고정이 우회되는 직접적인 원인은 무엇입니까?
- 해시 모양 브랜치 이름 방식에 한해, 깃허브 저장소에 이 방식이 적용되지 않는 이유는 무엇입니까?
1번 정답: 배경 자동 업데이트가 켜져 있으면 이미 설치된 플러그인이 사용자의 추가 확인이나 클릭 없이 교체될 수 있는 상태를 가리킵니다. 해설: 공격자의 실력이 아니라, 교체 과정에 사용자 확인 절차가 끼어들지 않는다는 점이 핵심입니다.
2번 정답: 에이전트가 커밋 해시로 코드를 받아온 뒤 실제로 받은 코드와 그 해시가 일치하는지 확인하지 않기 때문입니다. 해설: 일치 확인이 없으므로, 해시 모양 이름의 브랜치가 다른 코드를 가리키게 해도 에이전트는 고정된 버전으로 표시합니다.
3번 정답: 깃허브가 커밋 해시처럼 보이는 브랜치나 태그 이름을 허용하지 않기 때문입니다. 해설: 이 방식의 전제가 해시 모양 이름이므로 그 이름을 만들 수 없는 곳에서는 성립하지 않습니다. 단 제미나이 CLI의 FETCH_HEAD 방식은 별도이며, 이 제한으로 막히는지는 확립되지 않았습니다.