
전 직원에게 Claude Code를 배포했더니, 가장 어려운 판단은 '제한하는 것'이 아니라 '무엇을 제한하지 않을 것인가'였다.
요약
전 직원에게 Claude Code를 배포하며 겪은 보안 설정 및 권한 관리 경험을 공유합니다. 무조건적인 차단 대신 역할(Role)별로 공격 성립 조건을 분석하여 임계값을 다르게 설정하는 실무적인 접근 방식을 다룹니다.
핵심 포인트
- 전사 배포 시 보안과 업무 효율 사이의 균형이 핵심임
- 역할(Role)별로 권한 임계값을 차등 적용하여 업무 중단 방지
- Claude Enterprise 관리 콘솔을 통한 일괄 설정 메커니즘 활용
- 공격이 성립하는 조건만을 선별적으로 제한하는 설계 방침
전 직원에게 Claude Code를 배포했더니, 가장 어려운 판단은 '제한하는 것'이 아니라 '무엇을 제한하지 않을 것인가'였다.
전부 금지하면 현장이 멈춘다. 실제로 전사 전개 시 적용한 설정, 보류한 설정, 그리고 그 판단 이유를 정리한다.

서론
전 직원에게 Claude Code를 배포하게 되었다.
엔지니어만 사용한다면 어느 정도는 자기 책임으로 끝날 수 있다.
하지만 비엔지니어에게도 배포한다면 이야기가 달라진다.
Claude Code가 무엇을 할 수 있는지 모르는 상태에서
강력한 권한을 가진 도구를 건네게 된다.
그 리스크를 설계하는 것도 엔지니어의 업무였다.
처음에는 '보안적으로 올바른 설정'을 하나씩 전부 넣으려고 했다.
하지만 그렇게 하면 현장의 업무가 멈춘다.
최종적으로 도달한 결론은, 공격으로서 성립하는 조건이 갖춰지는 것만, 역할(Role)별로 임계값(Threshold)을 달리하여 제한한다는 사고방식이었다.
이 기사에서는,
- 실제로 적용한 설정
- 보류한 설정
- 그 판단 이유
까지 포함하여 공개한다.
※ 본 기사의 JSON 설정, 표, 수치는 판단의 사고방식을 전달하기 위한 예시입니다. 당사가 실제로 운용하고 있는 설정을 정확하고 망라적으로 나타내는 것은 아닙니다.
관리 콘솔이라는 메커니즘
개인별로 설정 파일을 수정하는 운용은 현실적이지 않다.
Claude Enterprise의 관리 콘솔(Management Console)에서 remote-settings.json을 배포하면, 전 직원에게 일괄적으로 설정을 적용할 수 있다.
게다가 공식 문서에 기재된 대로, managed settings로 정의한 환경 변수는 사용자 측에서 덮어쓸 수 없다.
즉,
'운용으로 지키는' 것이 아니라, '메커니즘으로 지키는'
상태를 만들 수 있다.

'전부 금지'는 파탄 난다
처음에는
Bash(curl *)
을 전 직원에게 금지하려고 생각했다.
하지만 엔지니어는 API 디버깅을 위해 GET 요청을 일상적으로 사용한다.
일률적으로 금지하면 일반적인 업무까지 멈춰버린다.
그래서 역할(Role)별로 임계값을 달리했다.
| 역할 | curl의 취급 | 이유 |
|---|---|---|
| 비엔지니어 | Bash(curl *) | 업무에서 사용할 일이 없음 |
| 엔지니어 | POST/PUT/DELETE/PATCH 등 쓰기 계열만 금지 | GET은 통상 업무에 필요 |
같은 문제는 allowManagedHooksOnly에서도 발생했다.
적용하면 이미 멤버들이 사용하고 있는 permission의 allow 리스트 운용까지 망가져 버린다.
여기서 사고방식을 바꿨다.
'설정할 수 있는 것을 전부 넣는' 것이 아니라, 공격이 성립하는 조건만을 역할별로 제한한다.
이것이 이번 설계 방침이 되었다.
실제로 적용한 설정
Claude.ai의 관리 콘솔에 JSON을 추가하는 것만으로 전 직원에게 자동 적용할 수 있다. MDM 배포는 필요 없다.

실제 관리 콘솔 화면. 여기에 settings.json을 작성하기만 하면 전 직원의 Claude Code에 반영된다.
엔지니어용 (발췌)
{
"minimumVersion": "2.0.65",
"cleanupPeriodDays": 30,
...
비엔지니어용 (차이점만 발췌)
쓰기 계열 curl의 개별 지정은 불필요해진다. Bash(curl *)의 완전 차단이 상위 호환으로서 작동하기 때문이다.
- "Bash(curl *-X POST*)",
- "Bash(curl *--data*)",
+ "Bash(curl *)",
무엇을 지키기 위한 설정인가
JSON만 봐서는 의도를 알기 어렵다.
설정은 크게 다음의 리스크를 방지하기 위해 넣었다.
| 카테고리 | 주요 설정 | 방지할 리스크 |
|---|---|---|
| 외부 통신 | wget / ssh / nc | 외부로의 통신 · 멀웨어 취득 |
| 파괴적 조작 | rm -rf / sudo | OS · 데이터 파괴, 권한 상승 |
| 난독화 | eval / base64 | 숨겨진 스크립트 실행 |
| Git | push --force / reset --hard | 이력 파괴 |
| 패키지 관리 | apt install | 미승인 소프트웨어 도입 |
| 인증 정보 | .env / AWS / SSH | 시크릿(Secret) 유출 |
| curl | POST 계열만 금지 (엔지니어) | 외부로의 데이터 전송 |
| 버전 | minimumVersion | 오래된 버전의 취약점 이용 |
| Bypass 봉인 | disableBypassPermissionsMode | 실행 전 확인 스킵 무효화 |
보류한 설정
사실, 대응한 설정보다 시간이 더 걸린 것은
"하지 않을 이유"를 결정하는 것이었다.
반년 뒤에
"왜 이걸 안 넣었었지?"
라는 상황을 방지하기 위해서라도, 판단 이유를 남겨두고 있다.
이하는 대표적인 2건만을 발췌한 것이다. 그 외에도 여러 설정에 대해 동일한 프로세스로 판단했으나, 상세 내용은 비공개로 한다.
| 설정 | 판단 | 이유 |
|---|---|---|
allowManagedHooksOnly | 보류 | 현 시점에서는 업무 영향이 큼 |
| GitHub Actions의 CI 설정 정비 | 대응하지 않음 | 프라이빗 리포지토리(Private Repo)만으로는 성립 조건을 충족하지 못함 |
"하지 않기로" 결정하는 데, "하기"보다 시간이 더 걸렸다.
놓치기 쉬웠던 설정
설정을 넣는다고 끝이 아니었다.
minimumVersion
오래된 Claude Code에서는 관리 콘솔 설정 자체가 적용되지 않는다.
즉,
최소 버전을 강제하지 않으면, 일부 직원에게만 제한이 적용되지 않는다.
disableBypassPermissionsMode
이것을 설정하지 않으면,
--dangerously-skip-permissions
만으로 실행 전 확인이 모두 무효화된다 (제한 자체가 무효화되는 것은 아니다).
다른 설정들이 의미를 갖는 것은, 이 실행 전 확인이 기능하고 있다는 전제가 있어야 가능했다.
그 판단의 배경이 된 공격 시나리오
이번 설정은 2025~2026년에 실제로 보고된 공격을 바탕으로 설계했다.
여기서는 일반적인 대책과 이번의 판단을 나누어 소개한다.
시나리오 1: 외부 리포지토리를 열었더니 API 키가 도난당했다
GitHub에서 발견한 리포지토리를 clone하여 Claude Code를 실행하는 것만으로, .claude/hooks/에 심어진 스크립트가 실행되어 API 키나 AWS 인증 정보가 외부로 전송되는 공격 (CVE-2025-59536 / CVE-2026-21852).
일반적인 대책
- devcontainer 내에서 열기
.claude/를 사전 확인하기allowManagedHooksOnly를 이용하기
이번의 판단
allowManagedHooksOnly는 보류했다. 현 시점에서는 외부 리포지토리를 Claude Code로 여는 운용 방식이 없으며, 적용할 경우 기존의 권한(Permission) 운용에 미치는 영향이 크기 때문에 운용 규칙으로 대체했다.
시나리오 2: GitHub Actions의 CI 시크릿이 유출되었다
PR 본문에 삽입된 지시를 Claude가 실행하여, CI 시크릿을 외부로 출력해 버리는 공격 ("Comment and Control" 공격, CVSS 9.4).
일반적인 대책
ps/env//proc계열의 명령어를 금지하기show_full_output: false(기본값)를 유지하기GITHUB_TOKEN의 권한을read로 제한하기
이번의 판단
프라이빗 리포지토리만 사용하는 운용 방식이며, 외부 공격자가 성립 조건을 충족할 수 없기 때문에 이번에는 설정 대상에서 제외했다.
시나리오 3: 악의적인 MCP를 추가했다
MCP의 도구 설명문(사용자에게는 보이지 않는 부분)에 숨겨진 명령을 작성하여 SSH 키 등을 훔치게 만드는 공격(Tool Poisoning Attack). MCP 서버는 나중에 정의를 다시 쓸 수 있다는 점도 까다롭다(Rug Pull).
일반적인 대책
allowManagedMcpServersOnly적용managed-mcp.json을 통한 allowlist 관리mcp-scan(Invariant Labs)을 통한 자동 검사.mcp.json을CODEOWNERS로 보호
이번의 판단
엔지니어는 "공식 MCP만 사용하고, 출처가 불분명한(野良) MCP는 넣지 않는다"라는 운영 규칙으로 대체했다. allowlist를 체계화하는 것은 관리 비용(棚卸しコスト) 대비 효율이 맞지 않아 대응하지 않는다. 반면, 비엔지니어 조직에서는 allowManagedMcpServersOnly를 적용할 예정이다(후술).
시나리오 4: Claude가 GitHub Actions의 issue를 읽고 운영 데이터를 유출했다
Claude가 ①기밀 데이터에 접근할 수 있고 + ②신뢰할 수 없는 외부 입력을 읽고 + ③외부에 쓸 수 있다라는 3가지 조건이 갖춰지면, 외부의 지시에 따라 자유롭게 데이터를 반출할 수 있는 상태가 된다. 이를 "Lethal Trifecta(죽음의 삼위일체)"라고 부른다.

일반적인 대책
외부를 읽는 역할과 쓰는 역할을 별도의 세션으로 분리한다. GitHub MCP에 write 권한을 부여하는 세션에서는 외부 입력을 직접 읽게 하지 않는다.
이번의 판단
기술적인 강제 조치는 아직 도입하지 않았으며, 운영 규칙으로서 개발 흐름(workflow)에 포함시키는 것을 우선시했다.
시나리오 5: Claude가 운영 DB의 테이블을 삭제했다
운영 DB의 DSN(연결 정보)이 환경 변수에 포함된 상태에서 마이그레이션(Migration)을 요청하여, Claude가 그대로 DROP TABLE을 실행해 버리는 사고(실제로 2025년 7월에 발생한 사례).
일반적인 대책
- 운영 DB의 연결 정보를 Claude가 동작하는 환경에 두지 않는다.
- DB 사용자에게 DDL 권한(
CREATE/DROP/ALTER)을 부여하지 않는다. - 마이그레이션은 CI의 인간 리뷰 필수 단계를 거치게 한다.
이번의 판단
dbhub MCP를 통해 엔지니어가 확인하며 사용하는 운영 방식으로 설정하였으며, 직접 SQL을 실행하는 것과 동일한 리스크로 간주하여 허용했다.
상세 공격 기법 목록 (참고)
CI/CD
pull_request_target+ fork checkout을 통한 시크릿 탈취 (HackerBot-Claw 공격)- PR 본문에 명령어를 심어 CI 시크릿을 훔침 (Comment and Control)
${{ github.head_ref }}등을 YAML에 직접 작성하면 임의의 명령어가 실행됨show_full_output: true로 설정하면 CI 로그에 시크릿이 출력됨
MCP
- 도구 설명문에 숨겨진 지시 (Tool Poisoning)
- 연결하는 순간 공격이 시작됨 (Line Jumping)
- 처음에는 무해하던 MCP가 나중에 유해하게 변함 (Rug Pull)
- 악의적인 MCP가 다른 MCP의 동작을 바꿔치기함 (Cross-server Shadowing)
코드베이스
.claude/hooks/에 심어진 스크립트가 Claude를 실행하기만 해도 실행됨- Claude가 존재하지 않는 패키지를 생성 $\rightarrow$ 공격자가 그 이름으로 악의적인 진짜 패키지를 공개 (slopsquatting)
- README 등에 눈에 보이지 않는 문자로 지시를 심음 (Invisible Unicode 공격)
에이전트
- 서브 에이전트(Sub-agent)를 경유하여 부모 에이전트보다 강력한 권한으로 동작함
git push --force등을 allowlist에 넣으면 브랜치를 망가뜨릴 수 있음- AWS/GCP의 CLI에 장기 키(Long-term key)가 전달되어 있으면 관리자 권한으로 클라우드를 조작할 수 있음
요약
이번에 가장 어려웠던 것은,
"무엇을 금지할 것인가"가 아니라, "무엇을 금지하지 않을 것인가"를 결정하는 것이었다.
공격 시나리오만 본다면 훨씬 더 많은 설정을 추가할 수도 있었다.
하지만 현장의 업무가 중단되면, 결국 설정 자체가 사용되지 않게 된다.
그렇기에 이번에 채택한 방침은,
- 공격이 성립하는 조건을 본다
- 역할(Role)에 따라 임계치(Threshold)를 다르게 설정한다
- 하지 않은 이유까지 기록한다
라는 것이었다.
보안 설정은 단순한 금지 사항의 목록이 아니다.
어디까지 허용하고, 어디서부터 시스템으로 방어할 것인가. 그 설계야말로 가장 어려운 판단이었다.
참고 소스
- Check Point Research: CVE-2025-59536 (리포지토리 포함 hook를 통한 RCE)
- Anthropic: GitHub Actions security guidance
- StepSecurity: HackerBot-Claw 공격의 상세 내용
- Invariant Labs: Tool Poisoning Attacks
- Simon Willison: The Lethal Trifecta
- JFrog: CVE-2025-6514 mcp-remote RCE
- Snyk: Slopsquatting (AI 생성 코드의 패키지 환각)
이전 기사
마치며
X (구 Twitter) 게시물에도 이 이야기를 작성했으니, 관심이 있다면 함께 확인해 보세요.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기