Claude Code 2.1.286을 자동 모드로 실행하던 한 관측 도구 제작자의 맥에서 테스트 코드의 버그가 실제 프로세스 네 개를 띄웠다. 두 프로세스는 JSON을 소리 내 읽었고, 나머지 두 개는 운영 서버에 데이터를 올리는 작업자였다. 에이전트에는 샌드박스가 없었지만 테스트 설정 덕분에 실제 세션이나 데이터는 전송되지 않았다.
사건은 2026년 10월 28일에 발생했다. 맥OS에서 일곱 개의 백그라운드 하위 에이전트가 각자 GitHub 이슈를 처리하며 코드를 작성하고 테스트를 실행했다. 에이전트들은 사용자의 권한으로 노트북에서 동작했고, 매 단계마다 승인을 받지 않았다.
16시 23분, 두 개의 음성이 겹쳐 들렸다. 원인은 에이전트가 작성한 테스트였다. 테스트는 사용자가 지정한 알림 프로그램의 예로 macOS의 say 명령을 사용했고, 테스트 실행 중 JSON 내용을 음성으로 읽었다. 에이전트는 테스트 실패 7초 뒤 버그를 고쳤지만, 실제 프로세스가 실행됐다는 사실은 보고하지 않았다. 맥 사용자에게 소리가 들린 것은 거의 4분 뒤였다.
테스트는 실제 명령을 실행하지 않도록 가짜 실행기를 전달했다. 하지만 코드가 가짜 실행기를 선택한 방식에 문제가 있었다.
spawn = spawn or _spawn # use the fake if given, else the real one
가짜 실행기는 빈 리스트였고, 파이썬에서 빈 리스트는 거짓으로 평가된다. 따라서 이 코드는 가짜 실행기 대신 실제 실행기를 선택했다. 실제 실행기는 명령을 분리된 프로세스로 실행해 테스트가 끝난 뒤에도 프로세스가 남을 수 있었다.
테스트는 say와 Codex가 각 작업 뒤 전달하는 JSON을 사용했다.
payload = json.dumps({"type": "agent-turn-complete", "thread-id": THREAD, "turn-id": "1"}) hook.handle("codex", ["--", "say", "done", payload], BytesIO(), spawned)
맥은 JSON을 음성으로 읽었다. 수정은 spawn = _spawn if spawn is None else spawn 한 줄이었다.
테스트 출력에 따르면 실제 실행기를 호출한 테스트는 세 개였고, 그 결과 사용자 계정으로 분리된 프로세스 네 개가 실행됐다. say 프로세스 두 개는 JSON을 읽었다. 나머지 두 개는 각각 Codex와 Claude Code 세션을 찾아 업로드하는 작업자였으며, 테스트에서는 올릴 세션이나 대화 기록을 찾지 못해 종료됐다.
작업자들은 테스트에서 엔드포인트를 지정하지 않아 기본 운영 수집 주소를 사용했다. 실제 데이터가 전송되지 않은 데는 테스트 설정이 모든 구성 디렉터리를 임시 폴더로 지정했고, API 키도 테스트용 가짜 값이었으며, 전송할 데이터도 없었다는 세 가지 이유가 있었다. 임시 폴더 설정이 없었다면 작업자는 실제 에이전트 대화 기록을 읽었을 수 있다. 그 기록에는 코드와 프롬프트, 에이전트에 평문으로 제공된 유효한 GitHub 토큰이 들어 있었다. 작업자는 이를 운영 서버로 올리려 했을 것이다.
테스트 실패 메시지에는 가짜 실행기가 아무것도 기록하지 않아 assert spawned == [...]가 [] == [...]로 실패했다는 내용이 있었다. 에이전트는 이를 읽고 버그를 고친 뒤 테스트 통과와 풀 리퀘스트만 상위 세션에 보고했다. 사건을 숨기려 한 것은 아니라고 제작자는 본다. 다만 실제 프로세스가 사용자 컴퓨터에서 실행된 일과 일반적인 테스트 버그를 구별해 알리는 절차는 없었다.
처음에는 대화 기록에서 ‘voice’를 검색했지만 관련 없는 결과만 나왔다. 맥OS 통합 로그에서 coreaudiod, corespeechd, say를 16시 20분부터 16시 29분까지 찾아본 뒤, 16시 23분 40초부터 16시 24분 1초까지 say 프로세스 두 개가 실행된 사실을 확인했다. 운영체제 로그가 실행된 일을 보여줬고, 그 시각을 대조해 에이전트와 테스트 버그를 찾았다.
제작자는 자신의 환경을 바꾸기 위해 에이전트별 샌드박스를 적용하고, 파일 쓰기를 각 작업 트리로 제한하며, 네트워크는 허용 목록으로 제한하고, 홈 디렉터리의 구성 파일에는 접근하지 못하게 하겠다고 밝혔다. 에이전트 지침에서 실시간 자격 증명을 제거하고 범위와 수명이 제한된 토큰을 사용하며, 테스트는 실제 실행기가 호출되면 실패하도록 바꿀 계획이다. 테스트 예시에서 실제 명령 대신 동작하지 않는 이름을 쓰고, 에이전트가 예상 밖의 부작용도 결과 보고에 포함하도록 하겠다고 했다. 사건은 앤스로픽에도 보고했다.
이번 일은 에이전트 한 개와 버그 하나가 관련된 단일 사건이며, 발생 빈도를 측정한 결과는 아니다. 제작자는 Claude Code가 특별히 더 위험하다고 주장하지 않는다. 샌드박스 없이 코드를 작성하고 실행하는 에이전트라면 같은 노출 가능성이 있다고 지적한다. 악의적인 행동이나 프롬프트 인젝션이 있었던 것도 아니다. 일반적인 코드 버그만으로도 부작용이 생겼다.
제작자는 병렬 백그라운드 에이전트에 샌드박스를 기본 적용하고, 에이전트가 실행한 프로세스를 확인할 수 있게 하며, 예상 밖의 부작용을 결과 보고에 포함하는 것이 필요하다고 제안한다. 에이전트가 작성한 코드는 사용자가 확인하기 전에 몇 초 만에 자신의 컴퓨터에서 실행될 수 있으므로, 그 코드가 접근할 수 있는 범위를 정해야 한다고 덧붙였다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요