AGENTS.md 보안, 남의 저장소에서 에이전트를 켜기 전 점검법

남이 만든 저장소에서 코딩 에이전트를 켜면 내가 입력하지 않은 지침이 문맥에 먼저 들어간다. Codex와 Claude Code가 시작할 때 정해진 경로의 지침 파일을 찾는 조건에서 그렇다. 공식 문서와 실험은 모두 2026-11-09 KST에 확인했다.

실행 전에 소스 코드뿐 아니라 지침 파일과 훅, MCP 설정 목록을 먼저 뽑아 읽어야 한다.

AGENTS.md 자동 로딩은 언제 일어나는가

왜 프롬프트에 없던 규칙이 응답에 따라붙을까. 에이전트는 세션을 시작할 때 정해진 경로의 파일을 찾아 문맥에 합치기 때문이다.

OpenAI의 Custom instructions with AGENTS.md 문서를 보면 Codex는 ~/.codex의 전역 지침에 이어 프로젝트 루트부터 현재 작업 디렉터리까지 내려간다. 디렉터리마다 AGENTS.override.md, AGENTS.md, project_doc_fallback_filenames에 지정한 이름 순으로 찾아 한 파일만 포함한다.

합친 크기가 project_doc_max_bytes 기본값 32 KiB에 도달하면 추가를 멈춘다. 현재 디렉터리까지의 경로만 보므로 하위 폴더 전체를 처음부터 읽지는 않는다.

실제로 반영되는지 macOS arm64의 codex-cli 0.166.0으로 시험했다. 프로젝트 AGENTS.md가 없는 새 Git 저장소에서 도구를 쓰지 말라는 프롬프트로 아래 명령을 실행했다.

codex --no-daemon --ask-for-approval never \
  -c 'log_dir="<폴더>/logs"' \
  -c 'sqlite_home="<폴더>/state"' \
  -c 'history.persistence="none"' \
  -c 'web_search="disabled"' \
  exec --ignore-user-config --ignore-rules --ephemeral \
  --sandbox read-only --color never --json \
  --cd <폴더>/repo \
  'Reply with READY. … Follow repository guidance …'

응답 이벤트는 아래와 같았고 도구 실행 이벤트는 없었다.

{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"READY"}}

다음으로 같은 저장소에 AGENTS.md를 만들고 무해한 지침 한 줄만 넣었다.

End your final answer with RADAR-MARKER-7.

프롬프트에 파일 이름도 마커도 넣지 않고 같은 명령을 다시 실행하자 응답 끝에 마커가 붙었다.

{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"READY\nRADAR-MARKER-7"}}

명령 실행이나 파일 읽기 이벤트가 없었으므로, 시작 시점에 저장소 지침이 문맥에 들어갔다고 본다. 내부 로더의 파일별 기록은 확보하지 못했다. SQLite 로그 조회는 빈 결과였고, 이 판단은 공식 문서와 두 실행의 응답 차이에 기댄다.

도구별 자동 로딩 범위와 실행 제어의 차이

왜 읽기 전용 모드나 신뢰 대화상자만으로 부족할까. 지침이 문맥에 들어가는 경로와 명령 실행을 막는 설정이 서로 다르기 때문이다.

Anthropic의 How Claude remembers your project 문서에 따르면 Claude Code는 현재·상위 디렉터리의 CLAUDE.md 계열을 시작할 때 읽는다. 하위 디렉터리 지침은 그 안의 파일을 다룰 때 불러온다. @path import 대상도 문맥에 함께 들어간다.

Security와 Configure permissions 문서를 보면 대화형 세션은 작업 공간 신뢰 대화상자와 .mcp.json 승인 절차를 거친다. claude -p는 이 두 대화상자를 띄우지 않는다.

신뢰하지 않은 폴더에서 claude -p를 돌리면 프로젝트 설정의 훅과 환경변수가 쓰일 수 있다. .mcp.json 서버도 묻지 않고 연결될 수 있다.

Cursor의 Rules 문서까지 더해 세 도구를 비교하면 다음과 같다.

구분CodexClaude CodeCursor
지침 파일AGENTS.override.md, AGENTS.md, fallback 이름CLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.md.cursor/rules/*.mdc, AGENTS.md
AGENTS.md루트부터 현재 폴더까지 디렉터리당 1개v2.1.277 이상, 프로젝트 CLAUDE.md 계열이 없으면 기본으로 대신 읽음루트와 중첩 지원
주의샌드박스와 승인 정책은 별개claude -p는 신뢰 대화상자 없음규칙마다 적용 시점이 다름

OpenAI의 Agent approvals & security 문서도 샌드박스와 승인 정책을 다른 제어로 구분한다. 읽기 전용은 비밀정보를 가리는 정책이 아니다. 읽을 수 있는 파일의 내용은 모델로 전달될 수 있다.

에이전트를 켜기 전에 무엇을 확인할까

저장소 복제, 지침 목록 읽기, 훅과 MCP 확인, 제한 실행의 네 단계를 화살표로 이은 점검 순서도. 에이전트 실행은 마지막 단계라고 적었다.

지침 검토와 훅·MCP 확인은 별개 단계이고, 에이전트 실행은 승인·샌드박스 설정을 확인한 뒤에 온다.

후보 목록은 아래 find로 뽑는다. 저장소 코드나 발견한 설정은 실행하지 않는 명령이다. 테스트용 중첩 지침과 빈 설정 파일을 넣은 저장소에서 실행하니 11개 경로가 나왔다.

find . -name .git -prune -o \
  \( -type f -o -type l \) \
  \( -name AGENTS.md -o -name AGENTS.override.md \
     -o -name CLAUDE.md -o -name CLAUDE.local.md \
     -o -name .cursorrules -o -name .mcp.json \
     -o -name .claude -o -name .codex -o -name .cursor -o -name .agents \
     -o -name SKILL.md -o -name copilot-instructions.md \
     -o -path '*/.cursor/rules' -o -path '*/.cursor/rules/*' \
     -o -path '*/.claude/rules' -o -path '*/.claude/rules/*' \
     -o -path '*/.claude/settings*.json' \
     -o -path '*/.codex/config.toml' -o -path '*/.codex/hooks.json' \
     -o -path '*/.cursor/hooks.json' -o -path '*/.cursor/mcp.json' \
     -o -path '*/.claude/hooks/*' -o -path '*/.codex/hooks/*' \
     -o -path '*/.claude/agents/*' -o -path '*/.claude/commands/*' \
  \) -print
./.cursor/hooks.json
./.cursor/rules/review.mdc
./.mcp.json
./.claude/settings.json
./.claude/rules/review.md
./.claude/CLAUDE.md
./.codex/config.toml
./AGENTS.md
./nested/AGENTS.override.md
./nested/AGENTS.md
./nested/CLAUDE.md
  1. 에이전트를 켜기 전에 복제한 폴더에서 위 find를 실행하고, git status --short로 현재 상태를 남긴다.
  2. 목록의 지침을 텍스트 뷰어로 읽는다. 상위 지시 무시, 검증 생략 같은 문장과 @path 대상을 확인한다.
  3. 훅 설정의 실행 명령과 스크립트 경로, .mcp.json의 실행 프로그램과 접속 대상을 읽는다.
  4. ~/.codex, ~/.claude/CLAUDE.md, 상위 폴더 지침처럼 find .에 잡히지 않는 범위를 따로 본다.
  5. 버전과 시작 디렉터리, 대화형 여부, 승인·샌드박스 설정을 확인하고 시작한다. claude -p라면 문서가 안내한 --setting-sources user, --settings '{"disableAllHooks": true}'를 검토한다.

이번 확인의 한계

Codex 실험은 단일 환경에서 조건별 1회, 무해한 마커가 붙는지만 본 것이다. 악성 명령, 승인 우회, 비밀 유출은 시험하지 않았다. 사용자 범위 AGENTS.md가 있는 환경이라 완전히 빈 프로필의 재현도 아니다.

Claude Code와 Cursor는 실행하지 않고 공식 문서로만 확인했다. 위 claude -p 옵션도 마찬가지다. find는 후보 이름을 보여 줄 뿐이라, 링크 대상과 직접 지정한 fallback 이름은 사람이 확인해야 한다.

지침 유무와 명시 인용이 구현을 어떻게 바꾸는지는 AGENTS.md 비우면 Codex도 fail-fast 안 지킨다와 Claude에 AGENTS.md 명시 인용했더니 fail-fast가 강해졌다에서 다뤘다.

결론

남의 저장소에서 에이전트를 켜면 프롬프트에 적지 않은 지침 파일이 시작 문맥에 들어올 수 있다. 결국 기준은 읽기 전용 모드나 신뢰 대화상자가 아니라, 지침 본문과 훅·MCP 설정을 먼저 읽었는가이다. 클론한 저장소가 있다면 에이전트를 켜기 전에 find로 목록부터 뽑아 읽어 보자.

댓글

이 블로그의 인기 게시물

AI 코딩 스킬, 많을수록 좋을까 — 자산이 부채로 바뀌는 손익분기

M4 Max 128GB 로컬 LLM 4종 속도 비교 — 실측 기록과 한계

Opus 5는 더 잘 쓰고, 더 AI답게 쓴다 — 세 모델 첫날 실측