Weir
AI 에이전트가 API 키를 유출하는 것을 포착하세요. 에이전트 프레임워크는 키를 트레이스(traces)와 로그(logs)에 복사할 수 있으며, 코딩 에이전트는 이를 모델의 컨텍스트(context)로 읽어 들일 수 있습니다. Weir는 정확한 값으로 각 키를 찾아내고, 어디로 갔는지 이름을 지정하며, 절대 출력하지 않습니다.
- 직접 구축한 에이전트: 가짜 키를 실제 키가 있는 곳에 심고, 에이전트 자체의 흐름(flows)을 실행하여 도달한 모든 장소: 스팬(spans), 로그(logs), 콘솔 출력, 모델, 기타 서비스에 대한 판정(verdict)을 받습니다. 유출되었는지, 정리되었는지, 아니면 불완전했는지를 확인합니다. MLflow에서 CVE-2026-116691 (GHSA-j7qq-vr8c-xvw3)를 발견했습니다.
- 사용하는 코딩 에이전트: Claude Code에서는 상태 표시줄(status line)을 통해 실제 키 중 어떤 것이 세션에 진입했거나 도구 호출(tool call)로 나갔는지 보여주며, 선택적 후크(optional hook)는 모델이 읽기 전에 알려진 키를 도구 결과에서 제거합니다.
CI PyPI License: Apache-2.0
Weir plants fake keys in your agent, lets its telemetry flow, and checks every span, log and metric for those exact values: leak, clean or incomplete.
10초 만에 사용해 보세요
pip install weir-scan
weir canary judge --sample
Terminal recording: weir canary judge --sample prints a LEAK line naming the planted fake key and the span it reached, then "result: leak", and exits 1.
두 가지 사용 방법
1. CI 또는 노트북에서 에이전트 테스트하기
weir-run은 실제 키가 있을 곳에 고유한 가짜 키를 심고, 로컬 가짜 모델을 대상으로 에이전트 자체의 흐름(flows)을 실행하여 에이전트가 내보내는 모든 것을 포착합니다. 이후 weir canary judge는 이 모든 것에서 해당 정확한 값들을 검색합니다.
pip install weir-scan weir-run
weir-run run --config canary.toml
[[placement]]
id = "env.OPENAI_API_KEY"
kind = "env"
...
풀 리퀘스트(pull request)의 경우, 한 단계가 이를 실행하고 판정 결과를 댓글로 게시합니다:
- uses: ralis-ai/weir@<ref>
설정(Config), pytest fixture 및 전체 워크플로우는 weir-run README · action README를 참조하세요.
에이전트 대신 자격 증명 스왑(credential swap) 또는 샌드박스(sandbox)를 확인하려면, weir-run verify --target iron-proxy가 식재된 키(planted key)를 통해 실행하고 배포 전에 서명하고 확인할 수 있는 기록을 작성합니다: docs/verify.md.
2. 사용자의 Claude Code 세션 모니터링하기 (Watch your own Claude Code sessions)
상태 표시줄 세그먼트(status-line segment)는 실제 자격 증명 중 몇 개가 세션의 컨텍스트(context)로 들어왔는지, 그리고 몇 개가 도구 호출(tool call)을 통해 나갔는지를 계산합니다. /weir를 사용하면 각각에 대해 출처, 이동한 턴(turn), 현재 위치, 취해야 할 조치 등을 설명해 줍니다. 값 자체는 절대 보여주지 않습니다.
설정(Setup)은 또한 마스킹 후크(redaction hook)를 추가할 수 있습니다. Read, Bash, Grep, Glob 또는 WebFetch 결과가 전체 값으로 사용자의 인벤토리 키(inventoried key) 중 하나를 포함하고, 이것이 weir audit에서 일치하는 형태일 경우, 해당 후크는 모델이 보기 전에 이를 [weir: NAME removed]로 대체하며, 상태 표시줄은 이를 외부로 유지된 것으로 계산합니다. Claude Code의 hooks reference에 따르면 이 대체는 "Claude가 보는 것만 변경"한다고 합니다. Bash 출력과 같이 약 30,000자를 초과하는 대용량 출력이 있는 경우, Claude Code는 세션 폴더의 파일로 전체 출력을 저장하고 그 경로를 Claude에게 제공합니다 (tools reference). 이 저장된 사본은 후크가 실행되기 전에 작성된 원본 출력을 담고 있으므로, 후크는 동일한 방식으로 소유자만 접근 가능한 형태로 다시 작성합니다. 만약 후크가 실패하면 상태 표시줄에 "possibly not redacted"라고 표시됩니다.
The weir segment beside an existing status line: a green check and "no known key seen", then a warning sign with "2 entered" in amber and "1 sent" in red.
uv tool install weir-scan
weir statusline setup
weir statusline undo가 이를 제거합니다. Linux 및 macOS에서 사용 가능합니다. 자세한 내용은: docs/statusline.md.
차별점 (Why it's different)
- 추측하지 않습니다. 플랜트된 정확한 값(원시 또는 인코딩된)을 찾기 때문에, 탐지되는 것은 실제 유출입니다.
- 모든 출구 경로를 확인합니다: 스팬(spans), 로그(logs), 메트릭(metrics), 콘솔 출력, 모델로 전송된 프롬프트, 그리고 다른 서비스로의 요청을 포함합니다. 비특권 사용자 네임스페이스(unprivileged user namespaces)가 허용되는 Linux 환경에서는 에이전트가 외부 네트워크 없이 실행되므로, 직접적인 연결도 포착됩니다.
- 테스트 환경에서 허위의 '모두 정상' 보고가 없습니다. 실행 과정에서 특정 항목을 사용하지 않았다면, Weir는 깨끗하다(clean)고 말하는 대신 불완전하다(incomplete)고 표시하며 정확히 무엇을 확인했는지 보여줍니다. 종료 코드: 0은 깨끗함(clean), 1은 유출(leak), 2는 사용할 수 없는 입력(unusable input), 3은 불완전함(incomplete).
- 오프라인이며 결정론적입니다(deterministic). 어떤 AI 모델도 아무것도 결정하지 않으며, Weir 자체도 어딘가로 아무것도 전송하지 않습니다. 테스트는 이 두 가지를 모두 강제합니다.
Weir로 발견된 취약점: CVE-2026-116691 (GHSA-j7qq-vr8c-xvw3)은 MLflow 권고 사항이며, 3.17.0 버전에서 수정되었습니다.
제한 사항 (Limits)
- 해시되거나(hashed), 분할되거나(split), 잘린 값(truncated)이 아닌, 전체 값만 찾습니다.
- 테스트가 실행되는 동안 에이전트가 전송하는 것만을 볼 수 있습니다.
- 네트워크 격리(Network isolation)는 Linux에서만 가능하며 비특권 사용자 네임스페이스가 필요합니다. 다른 환경에서는 보고서에 네트워크가 격리되지 않았다고 명시됩니다.
- 가짜 모델은 OpenAI 호환 및 Anthropic 메시지 API를 사용합니다.
- 상태 표시줄(status line)은 인벤토리 내의 키만을 전체 값으로 알고 있습니다. 파일 내부나 변수 이름으로 남는 키는 감지되지 않습니다.
- 인벤토리는 한 번에 하나의 프로젝트를 다룹니다.
전체 목록은 docs/canary.md와 docs/statusline.md에 있습니다.
마스킹(redaction) 훅:
- 모델이 툴 호출(tool call) 후에 읽는 내용만 변경합니다. 이미 실행된 명령을 되돌리거나 채팅에 붙여넣은 키를 포착할 수는 없습니다.
- 인벤토리(inventory)된 키와는 전체 값만 일치시킵니다. 다른 텍스트에 붙어 있거나 PDF 내부에 있는 키는 제거되지 않습니다.
- 후크(hook)가 완료되지 않거나 툴 호출이 실패하면, Claude Code는 원래 출력을 그대로 전달합니다. 이 경우 상태 표시줄에는 녹색이 아닌 "possibly not redacted" 또는 "entered"가 표시됩니다.
전체 목록: docs/statusline.md#the-redaction-hook
또한 포함된 기능 (Also in the box)
weir scan: 이미 가지고 있는 흔적(traces)을 따라 민감한 데이터를 추적합니다. 예를 들어 신뢰할 수 없는 툴 출력에서 나가는 이메일까지입니다.
weir inventory: 에이전트(agent)가 접근할 수 있는 자격 증명(credentials)을 이름만으로 목록화합니다.
weir audit: 저장된 에이전트 세션과 사용자의 실제 자격 증명을 오프라인 상태에서 확인합니다.
FAQ
실제 키가 필요한가요? 아니요. 테스트는 가짜 값만 사용합니다. 상태 표시줄의 경우, Weir는 실제 키 자체를 저장하는 것이 아니라 키화된 지문(keyed fingerprints)만 저장합니다.
gitleaks나 trufflehog와 어떻게 다른가요? 이들은 코드에서 비밀처럼 보이는 문자열을 찾습니다. Weir는 특정 값이 실제로 에이전트를 통해 외부로 나갔는지 여부를 증명합니다. 둘 다 사용하세요.
어딘가로 무언가를 전송하나요? 아니요. 가짜 모델은 127.0.0.1에서만 수신하며 아무것도 전달하지 않으며, 스캐너는 네트워크 연결을 열지 않습니다. 테스트는 이 두 가지를 모두 강제합니다.
라이선스 (License)
Apache-2.0이며, 모든 것이 영구적입니다. 아무것도 보류되지 않고, 제한되지 않으며, 집에 전화를 거는(phoning home) 것도 없습니다.
왜 "weir"인가요?
<p align="center">
<img src="https://raw.githubusercontent.com/ralis-ai/weir/main/docs/assets/weir.jpg" alt="A weir: a low dam across a river, with water flowing evenly over its crest" width="560">
<br>
<em>위어(weir)는 강물의 흐름을 측정하는 낮은 댐입니다. 물은 계속 움직이지만, 측정은 어쨌든 이루어집니다.</em>
<br>
<sub>Damhead Weir, Water of Leith. Photo by 501ghost, Wikimedia Commons, CC0.</sub>
</p>