본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 15. 15:33

Claude Code로 API 키가 유출되는 것을 방지하는 방법

요약

Claude Code 사용 중 API 키가 프롬프트나 세션 기록에 노출되는 문제를 해결하기 위한 오픈 소스 플러그인 'Keyward'를 소개합니다. Keyward는 훅(hook)을 통해 키를 탐지하고, OS 레벨의 자동화를 활용해 키를 안전한 참조값으로 교체하여 재전송합니다.

핵심 포인트

  • Claude Code의 UserPromptSubmit 훅은 프롬프트 재작성이 불가능하고 차단만 가능함
  • Keyward는 키를 탐지하여 로컬에 안전하게 저장하고 프롬프트 내 키를 참조값으로 대체함
  • OS 레벨 자동화를 통해 차단된 프롬프트를 정화된 텍스트로 자동 재전송하는 우회 방식 사용
  • API 키 유출 방지를 위한 자동화된 보안 워크플로우 제공

Claude Code에 API 키를 붙여넣을 때마다 다음과 같은 작은 경고가 떴습니다: "이 키가 유출되었을 수 있습니다 — 키를 교체(rotate)하세요.""

그리고... 네, 알고 있습니다. 그 시점에는 이미 키가 요청(request)에 포함되어 있고, 제 세션 기록(session transcript)에 영원히 남게 됩니다. 키를 교체하는 것은 사후 처리일 뿐, 근본적인 해결책이 아닙니다.

키를 참조할 때마다 매번 교체하고 싶지는 않았고, "그냥 조심하자"라는 다짐은 속도를 내어 작업하는 순간 — 즉, 바이브코딩(vibecoding)을 하고 있는 대부분의 시간 — 무용지물이 됩니다. 그래서 저는 '조심하는 부분'을 자동화하기로 했습니다.

그것의 이름은 Keyward입니다 — 작고 오픈 소스인 Claude Code 플러그인입니다. 여기 그 아이디어와, 이를 제작하면서 직면했던 정말 까다로웠던 부분에 대해 설명하겠습니다.

정확한 문제점

채팅에 비밀 값(secret)을 붙여넣으면 다음과 같은 일이 발생합니다:

  1. 프롬프트(prompt)의 일부로서 Anthropic의 API로 전송됩니다.
  2. 로컬의 *.jsonl 기록(transcript)에 기록됩니다.
  3. Claude가 (정확하게) 유출되었다고 알려줍니다.

한 번의 붙여넣기로 세 곳에 영향을 미칩니다. 경고를 다 읽기도 전에 이미 피해는 발생한 상태입니다.

Keyward가 하는 일

UserPromptSubmit 훅(hook)이 사용자가 제출하는 모든 메시지를 스캔합니다. 키를 발견하면 다음과 같이 동작합니다:

  1. 탐지(detects): 약 20개의 제공업체에 대한 정규 표현식(regex), 명시적인 /key 마커, 선택적인 gitleaks를 사용합니다.
  2. 저장(saves): 값을 ~/.claude/secrets/<name>.txt에 저장합니다 (chmod 600).
  3. 차단(blocks): 원본 프롬프트를 차단하여 가공되지 않은 값이 모델에 도달하지 않도록 합니다.
  4. 재전송(re-submits): 메시지의 정제된(sanitized) 버전을 다시 제출합니다 — 키는 <<secret:NAME stored at ~/.claude/secrets/NAME.txt>>로 대체됩니다.

사용자는 Enter를 한 번만 누르면 되며, 모델은 오직 참조값만을 보게 됩니다.

까다로운 부분: 프롬프트를 수정할 수 없고, 오직 차단만 가능하다

이 부분은 저를 놀라게 했기에 공유할 가치가 있습니다.

Claude Code의 UserPromptSubmit 훅은 메시지가 모델에 도달하기 에 실행되므로, 키를 잡아내기에 완벽한 장소입니다. 하지만 설계상, 해당 훅은 프롬프트를 다시 작성(rewrite)할 수 없습니다. 오직 다음 작업만 가능합니다:

  • 프롬프트와 함께 컨텍스트를 추가하거나,
  • 프롬프트를 완전히 **차단(block)**하는 것.

이는 의도적인 안전 설계입니다. 프롬프트를 조용히 재작성할 수 있는 훅(hook)은 매우 위험한 공격 표면(attack surface)이 될 수 있기 때문입니다 (예를 들어, 플러그인이 사용자의 "파일 X 삭제"를 몰래 "파일 Y 삭제"로 바꾸는 상황을 상상해 보십시오).

따라서 "키를 감지하고 조용히 교체하는 것"은 직접적으로 불가능합니다. Keyward의 우회 방법은 다음과 같습니다:

# intercept.py (단순화 버전)
detection = detect(prompt)
if detection["secrets"]:
...

이 훅은 유출될 프롬프트를 차단(block)하고, **OS 레벨의 자동화 (OS-level automation)**를 통해 정화된(sanitized) 텍스트를 붙여넣고 Enter 키를 대신 눌러주는 아주 작은 분리된 프로세스를 생성합니다. 사용자 입장에서는 차단된 메시지가 깜빡인 후, 깨끗한 메시지가 그 자리를 대신하게 됩니다. 키 입력은 단 한 번뿐입니다.

크로스 플랫폼 붙여넣기 (Cross-platform paste)

붙여넣기 백엔드는 OS별로 다르며, 각 백엔드는 클립보드를 저장하고, 타이핑하고, 포커스가 변경되지 않았는지 확인한 후 클립보드를 복구합니다:

  • macOSosascript (손쉬운 사용(Accessibility) 권한 필요)
  • Linux X11xdotool
  • Linux Waylandwtype (컴포지터(compositor)에 따라 다름: Sway/Hyprland는 지원, GNOME은 기본적으로 미지원)
  • Windows — PowerShell SendKeys

디스플레이 서버가 없는 경우(SSH, Docker)? KEYWARD_DISABLE_PASTE=1로 설정하십시오. 데이터는 여전히 저장 및 정화되지만, 붙여넣기는 수동으로 수행해야 합니다.

재유출 없이 저장된 키 사용하기

내장된 기술을 통해 Claude가 비밀 정보를 출력하지 않고 소비하도록 학습시킵니다:

export GITHUB_TOKEN=$(cat ~/.claude/secrets/github_pat_classic.txt) && gh api /user

...절대로 생으로 cat 명령어를 사용하지 않습니다 (이는 값을 컨텍스트로 곧바로 덤프하게 됩니다). 값은 디스크 → 프로세스 환경 변수(process env) → 도구(tool)로 흐르며, 표준 출력(stdout)을 통해서는 절대 전달되지 않습니다.

솔직히 말해서: 이것은 마법이 아니라 심층 방어 (defense-in-depth)입니다

비밀 정보는 chmod 600 권한의 평문으로 저장됩니다. 이는 ~/.aws/credentials.env 파일과 동일한 신뢰 모델이며, 저장 시 암호화(encrypted at rest)되지는 않습니다. Keyward는 **"지금 당장 채팅에서 이 키를 한 번 사용해야 해"**라는 워크플로우를 위한 안전망이지, 실제 비밀 관리자(secret manager)를 대체하는 것이 아닙니다. README와 위키(wiki)에는 이 도구가 무엇을 보호하고 무엇을 보호하지 않는지가 정확히 문서화되어 있으며, 이는 보안 도구로서 올바른 방향이라고 느껴집니다.

시도해 보기

Claude Code 세션에서:

/plugin marketplace add albemiglio/keyward
/plugin install keyward@keyward

자유 및 오픈 소스 (MIT) — github.com/albemiglio/keyward. 약 35개의 테스트, macOS/Linux/Windows 전반에 걸친 CI(지속적 통합), 네트워크 호출 없음, 텔레메트리 (Telemetry) 없음.

만약 AI 도구에 키를 붙여넣고 결과가 좋기만을 바랐던 적이 있다면 — 이것이 바로 그 안전망입니다. 🔑

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0