스테이징 데이터베이스를 확인하거나 외부 API를 호출하려고 AI 코딩 에이전트가 제안한 명령을 승인한다. 화면에서는 한 번의 실행 승인처럼 보이지만, 조직이 확인해야 할 지점은 그 다음이다. 에이전트가 승인한 명령을 다시 묻지 않기 위한 규칙으로 저장하는가, 저장한다면 그 규칙에 토큰·비밀번호·연결 문자열이 남는가, 그 파일이 Git 추적 대상이 되는가를 봐야 한다.
이번에 공개적으로 확인된 사례는 Claude Code의 동작과 관련된다. 조사 내용에 따르면 Claude Code에서 명령 실행 요청에 대해 “Yes, and don't ask again”을 선택하면, 승인한 명령 문자열이 프로젝트 디렉터리의 .claude/settings.local.json에 저장될 수 있다. 명령 안에 비밀정보가 포함돼 있었다면 그 값도 함께 평문으로 남을 수 있다.
따라서 의사결정 질문은 “AI 코딩 에이전트에게 셸 명령 실행을 허용할 것인가”가 아니다.
우리 조직은 승인된 명령이 어디에 저장되는지 확인했고, 비밀정보가 포함된 승인 규칙은 어떤 조건에서 차단·검토·폐기할 것인가.
이 질문은 특정 제품의 취약점 목록을 만드는 일이 아니다. 다만 각 제품의 저장 방식은 다를 수 있으므로, 도입 전에 제품별로 확인해야 할 경계를 정하는 일이다.
실패는 승인 버튼이 아니라 재사용 파일에서 시작된다
명령 실행 자체가 항상 위험한 것은 아니다. 로컬 테스트, 포맷, 린트, 빌드처럼 외부 계정이나 민감한 환경에 접근하지 않는 작업은 반복 실행할 이유가 충분하다.
문제는 데이터베이스 접속, 배포 상태 확인, 외부 API 호출, SSH 접속처럼 자격증명이 필요한 작업이다. 개발자가 환경변수 값을 명령행에 직접 넣거나, 연결 문자열과 비밀번호를 포함한 명령을 승인할 수 있다. 그 명령이 승인 규칙으로 저장되면 비밀정보는 더 이상 실행 시점에만 존재하지 않는다. 개발 장비의 파일, 프로젝트 디렉터리, 커밋 후보 목록, 저장소 이력으로 이동할 가능성이 생긴다.
공개 GitHub를 대상으로 한 조사에서는 .claude/settings.local.json 파일 104,185개 가운데 1,122개에서 실제 비밀정보가 확인됐다. 조사에서 식별된 값에는 공급자 형식의 키뿐 아니라 데이터베이스 비밀번호, API 토큰, 공개 호스트와 함께 저장된 자격증명도 포함됐다.
여기서 주의할 점이 있다. 비밀정보 탐지 도구가 통과했다고 해서 명령 승인 파일이 안전하다고 단정하기 어렵다. 키처럼 일정한 형식을 가진 값은 탐지하기 상대적으로 쉽지만, 명령문 안의 비밀번호나 연결 문자열은 다른 텍스트와 섞일 수 있다. 조사에서도 일부 파일은 널리 쓰이는 두 비밀정보 탐지 도구 모두에서 탐지되지 않았다고 설명한다.
실패 경로는 대체로 다음처럼 이어진다.
- 개발자가 비밀정보를 포함한 명령을 승인한다.
- 에이전트가 그 명령 또는 허용 규칙을 로컬이나 프로젝트 내부 파일에 저장한다.
- 설정 파일이 일반 코드 변경과 함께 Git 변경 목록에 나타난다.
- 개발자 또는 자동화가 해당 파일을 커밋한다.
- 저장소 이력, 포크, 기존 클론에 비밀정보가 남는다.
실행 권한만 검토하면 이 경로의 절반을 놓친다. 승인 결과가 어떤 파일로 남는지까지 확인해야 한다.
자동 승인은 명령의 쓰기 여부만으로 나누기 어렵다
명령을 읽기 전용과 쓰기 작업으로 구분하는 정책은 유용하다. 다만 비밀정보 저장 위험을 판별하는 기준으로는 부족하다. 읽기 전용 데이터베이스 조회라도 명령행 인수에 비밀번호가 들어가면, 승인 규칙 파일에 비밀정보가 남을 수 있기 때문이다.
자동 승인 정책은 아래 네 가지를 함께 보아야 한다.
| 판단 항목 | 자동 승인 후보 | 검토 또는 차단 후보 |
|---|---|---|
| 명령 문자열 | 비밀값 없는 로컬 테스트, 린트, 포맷, 빌드 | 토큰, 비밀번호, 연결 문자열, SSH 자격증명이 포함된 명령 |
| 접근 대상 | 외부 인증 없이 수행하는 로컬 작업 | 운영·스테이징 환경, 클라우드 계정, 외부 API |
| 저장 결과 | 저장 위치와 내용이 확인됐고 Git 추적 대상이 아닌 경우 | 프로젝트 내부 또는 공유 설정에 명령 전문이 저장되는 경우 |
| 권한 범위 | 작업 범위가 제한된 자격증명 | 관리자 권한, 계정 전체 권한, 만료 조건이 불명확한 장기 자격증명 |
이 표는 어떤 제품이 반드시 이렇게 동작한다는 뜻이 아니다. 제품별로 승인 규칙 저장 위치, 설정 파일 이름, 공유 설정 방식이 다를 수 있다. 그러나 에이전트 평가와 운영 정책에서 이 네 항목을 확인하면, “명령을 실행해도 되는가”라는 좁은 질문을 “비밀값이 어디에 남는가”라는 운영 질문으로 바꿀 수 있다.
특히 TOKEN=값 curl ...처럼 비밀값이 완성된 명령 문자열에 들어가는 방식은 자동 승인 후보에서 빼는 편이 낫다. 에이전트가 작업을 수행해야 한다면, 조직은 비밀값이 승인 규칙 자체에 들어가지 않는 실행 경로를 검토할 수 있다. 이때 검증할 대상은 명령의 성공 여부만이 아니다. 승인 뒤 생성되거나 수정된 파일, 그리고 Git 상태에서 그 파일이 추적 후보로 보이는지까지 함께 확인해야 한다.
조기 신호는 보안 사고 보고서보다 PR 변경 목록에서 먼저 보인다
이 유형의 문제는 대개 장애 알림으로 시작하지 않는다. 개발 편의를 위해 만들어진 설정 파일이 코드 변경에 섞이고, 시간이 지난 뒤 공개 저장소나 내부 점검에서 발견될 수 있다. 그래서 보안팀의 사후 스캔만 기다리기보다 개발 흐름 안에서 재검토 신호를 정해 두는 편이 낫다.
다음 상황이 보이면 자동 승인 범위와 저장 정책을 다시 확인할 시점이다.
- 프로젝트 루트나 하위 디렉터리에 에이전트 설정 파일이 새로 생성된다.
- 승인 규칙 파일에 URL, 데이터베이스 호스트, 사용자명, 토큰, 비밀번호처럼 보이는 값이 함께 남는다.
- 개인 환경의 접속 명령을 팀 공용 설정에 넣자는 요청이 생긴다.
- 코드와 무관한 에이전트 설정 파일이 PR에 반복해서 포함된다.
- 비밀정보 탐지 결과는 없지만, 명령 문자열을 사람이 검토하지 않았다.
- 운영 점검을 위해 개발자 장비에 장기 자격증명이나 광범위한 권한의 키를 배포하고 있다.
여기서 중요한 것은 설정 파일을 모두 금지하는 일이 아니다. 팀이 공유할 설정이 필요한 경우도 있다. 다만 공유 파일에는 비밀값을 포함한 명령 전문을 넣지 않는다는 조건을 명확히 둘 필요가 있다. 공유할 수 있는 것은 작업 방식, 허용할 명령 범위, 비밀값 없는 패턴이어야 한다. 개인 계정의 접속 정보나 특정 환경의 비밀번호가 되어서는 안 된다.
저장과 커밋 경계는 제품 평가 단계에서 시험해야 한다
Claude Code 사례에서 확인된 핵심은 전역 Git ignore만으로는 모든 상황을 막지 못할 수 있다는 점이다. 해당 조사에서는 로컬 설정 파일이 전역 ignore에 추가되는 방식이 설명됐지만, 새로 저장소가 된 폴더, 다른 장비에서의 복제, 이미 추적 중인 파일 같은 경우에는 보호가 이어지지 않을 수 있다고 지적했다.
여기서 “프로젝트별 ignore”라고 뭉뚱그려 말하면 부족하다. 팀이 함께 쓰는 저장소의 .gitignore 파일에 제외 규칙을 커밋하면, 그 규칙은 해당 저장소를 받는 구성원에게 함께 전달된다. 반면 개발자 개인의 전역 ignore 설정은 저장소와 함께 배포되지 않는다. 조직이 특정 에이전트의 로컬 설정 파일을 저장소에 두지 않기로 했다면, 다음을 제품 검증 항목으로 삼을 수 있다.
- 자동 승인 선택 뒤 어떤 파일이 어느 경로에 생성되는지 확인한다.
- 승인 규칙이 명령 전문을 저장하는지, 비밀값이 평문으로 남을 수 있는지 확인한다.
- 새 저장소, 기존 저장소, 이미 파일이 추적된 상태에서 Git 상태가 어떻게 달라지는지 확인한다.
- 저장소의
.gitignore에 제외 규칙을 넣을지, 사전 커밋 또는 CI에서 파일 경로 자체를 차단할지 정한다. - 공유 설정을 허용한다면 그 파일에 들어갈 수 있는 값과 금지할 값을 문서화한다.
이 순서는 제품 기능을 불신하자는 제안이 아니다. 제품이 제공하는 기본 보호와 조직의 저장소 운영 규칙은 별개일 수 있기 때문이다. 기본 보호가 있어도 팀의 커밋 흐름과 저장소 생성 방식까지 대신 통제하지는 않는다.
노출 대응은 파일 삭제보다 자격증명 무효화가 먼저다
설정 파일이나 Git 이력에서 비밀정보를 발견하면, 먼저 그 값이 아직 접근에 사용될 수 있는지 판단해야 한다. GitHub는 저장소 이력에 비밀정보가 노출된 경우 이력을 정리하기 전에 해당 비밀정보를 폐기하거나 교체하라고 안내한다.
이력 재작성은 필요한 상황이 있을 수 있지만, 자동으로 따라야 하는 첫 단계는 아니다. 기존 클론과 포크에 값이 남아 있을 수 있고, 협업자가 이전 이력을 다시 푸시해 비밀정보가 재유입될 위험도 있다. 커밋 해시가 바뀌면서 자동화와 PR 검토 기록에 부작용이 생길 수 있다는 점도 고려해야 한다.
따라서 대응 절차는 다음처럼 정리하는 편이 현실적이다.
- 노출된 키, 토큰, 비밀번호의 접근 권한을 폐기하거나 교체한다.
- 해당 자격증명이 어떤 시스템과 권한 범위에 연결됐는지 확인한다.
- 중앙 저장소, 브랜치, 이력에서 제거 조치가 필요한지 결정한다.
- 기존 클론, 포크, 열려 있는 브랜치, 협업자 작업을 고려해 이력 정리 범위를 조율한다.
- 같은 파일과 같은 승인 방식이 다시 커밋되지 않도록 저장·검사·승인 정책을 수정한다.
CTO와 개발 리드가 도입 회의에서 먼저 정할 것은 자동 승인 버튼을 몇 번 누르게 할지가 아니다. 에이전트가 승인 결과를 어디에 남기는지, 그 파일이 커밋되면 누가 차단하는지, 노출이 발견되면 누가 어떤 권한으로 키를 폐기하는지를 정해야 한다. 자동화는 그 경계가 합의된 뒤에 넓혀도 늦지 않다.