우리가 놓친 `rg`

Codex를 VS Code 내장 터미널에서 실행하다 보면, 가끔 이상한 팝업이 떴습니다.
rg를 열 수 없다는 macOS 보안 경고였습니다.
팝업만 보면 꽤 심각했습니다. 당장 실행이 막힌 것처럼 보였고, 처음에는 흔한 로컬 환경 문제라고 생각했습니다. 어딘가에 있는 rg 바이너리에 quarantine 속성이 붙었고, macOS가 그 실행을 막고 있는 것처럼 보였습니다.
그런데 이상한 점이 있었습니다.
Codex는 전혀 당황하지 않았습니다.
로그는 계속 흘러갔습니다.
Codex는 언제나처럼 Ready 상태까지 도달했습니다.
시스템은 비상인 것처럼 굴었는데, Codex는 아무 일도 없다는 듯 계속 일했습니다.
팝업은 문제의 전부가 아니었다

팝업은 반복적으로 나타났습니다.
조건도 꽤 좁았습니다. iTerm2에서는 재현되지 않았고, VS Code 내장 터미널에서 Codex를 돌릴 때 일관되게 나타났습니다.
처음에는 금방 끝날 줄 알았습니다. 익숙한 보안 팝업이고, 익숙한 이름의 실행 파일이었으니까요.
하나를 확인했습니다. 아닌 것 같았습니다. 또 하나를 확인했습니다. 이번에도 아니었습니다. 끝난 줄 알았는데 다시 떴고, 그때마다 “아직 아니네”라는 쪽으로 삽질이 밀려났습니다.
이 시점에서 자연스러운 질문은 하나였습니다.
rg가 어디 있지?
그래서 눈에 보이는 후보들을 확인했습니다.
Homebrew로 설치된 rg.
VS Code가 가지고 있는 rg.
OpenAI VS Code 확장 안에 있는 rg.
Copilot이 들고 있는 rg.
전부 정상처럼 보였습니다.
quarantine 속성은 없었습니다. 적어도 내가 확인한 위치에서는 그랬습니다.
spctl도 봤습니다.
Homebrew rg.
VS Code, OpenAI 확장, Copilot 쪽의 rg.
모두 같은 결과였습니다.
그 출력만으로는 아직 범인을 특정할 수 없었습니다.
문제는 계속 남아 있었고, 의심할 만한 파일은 하나씩 사라졌습니다.
범인을 좁혀가는 과정은 다시 막혔습니다.
질문을 바꾸다
여기서 손이 잠깐 멈췄습니다.
파일을 더 찾는다고 풀릴 문제가 아닌 것 같았습니다. 이미 흔한 위치는 봤고, 그 결과는 모두 같은 방향을 가리키고 있었습니다.
rg는 문제가 없어 보였습니다.
하지만 그 말은 정확하지 않았습니다.
우리가 확인한 rg가 문제가 없어 보였던 것입니다.
그때까지 묻고 있던 질문은 이쪽이었습니다.
rg, 대체 어디 있지?
그 질문은 틀린 질문은 아니었습니다. 다만 충분하지 않았습니다.
Codex가 실제로 실행하는 바이너리를 찾으려면 질문을 바꿔야 했습니다.
팝업을 띄운 rg는 대체 누구야?
그때부터 흐름이 달라졌습니다.
이제 관심사는 시스템 안에 존재하는 모든 rg가 아니었습니다. Codex 실행 경로 안에서 실제로 호출되는 rg였습니다.
Codex가 실제로 실행한 rg
질문을 바꾸자, 지금까지 보이지 않던 경로가 하나 들어왔습니다.
Codex cask 안에 번들된 rg였습니다.
확인된 경로의 예는 이렇습니다.
/opt/homebrew/Caskroom/codex/0.144.1/codex-path/rg
이번에는 결과가 달랐습니다.
그 바이너리에는 quarantine 속성이 남아 있었습니다.
마지막 퍼즐 조각이 맞았습니다.
앞선 확인들이 틀렸던 것은 아니었습니다. Homebrew의 rg, VS Code의 rg, OpenAI 확장의 rg, Copilot의 rg는 모두 확인한 그대로였습니다.
다만 Codex가 실행하던 rg가 아니었습니다.
그래서 후보를 하나씩 지우는 과정이 길어졌습니다. 같은 이름의 실행 파일을 보고 있었지만, 같은 실행 경로를 보고 있지 않았습니다.
같은 환경에서 다시 실행해 보기
마지막으로 필요한 것은 재현이었습니다.
Codex가 들고 있던 번들 rg를 VS Code 내장 터미널에서 직접 실행했습니다.

이 장면이 결정적이었습니다.
팝업이 바로 나타났습니다.
너였구나.
팝업은 VS Code 내장 터미널에서 재현되었습니다. 일반적인 rg 후보들에는 quarantine 속성이 없었습니다. Codex 번들 rg에는 그 속성이 있었습니다. 그리고 그 바이너리를 같은 환경에서 직접 실행하자 같은 팝업이 떴습니다.
더 이상 “어딘가의 rg 문제일 것 같다”가 아니었습니다.
Codex가 실제로 실행하는 rg를 찾았고, 그 파일로 증상을 재현했습니다.
해결보다 중요한 것
해결은 언제나처럼 심플했습니다.
Codex 번들 rg에서 quarantine 속성만 제거했습니다.
xattr -d com.apple.quarantine "$CODEX_RG"
Codex의 문제도 아니었습니다.
VS Code의 문제도 아니었습니다.
확인된 단 하나의 바이너리만 수정했습니다.
그 뒤 팝업은 사라졌습니다.
Codex는 여전히 실행됐고, 언제나처럼 Ready까지 갔습니다.
달라진 것은 중간에 끼어들던 보안 팝업뿐이었습니다.
한 줄 명령으로 끝난 것처럼 보이지만, 실제로는 같은 이름의 다른 실행 파일을 찾으면서 끝난 일이었습니다.
Homebrew의 rg가 아니었습니다.
VS Code의 rg도 아니었습니다.
Codex가 실제로 실행한 rg였습니다.
이번 삽질은 다행히 여기서 마무리입니다.
이제 또 다른 삽질을 하러 가야죠.
References
-
OpenAI. Codex CLI Documentation.
https://github.com/openai/codex -
Apple Developer Documentation. File System Programming Guide — Extended Attributes (xattr).
https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemDetails/FileSystemDetails.html