"매 secret 의 leak 은 git history 의 forever — 매 prevention(pre-commit) > detection(CI) > remediation(rotate + rewrite history)". 매 origin 은 2014 GitHub 의 AWS key 대량 leak; 매 modern state 는 gitleaks/trufflehog v3 (entropy + verifier), GitHub Push Protection, AI-aided context analysis (Claude Opus 4.7 으로 매 false positive triage).
매 핵심
매 detection 의 3 layer
Pre-commit (local): gitleaks pre-commit hook — 매 push 전 차단.
CI (PR): gitleaks/trufflehog GitHub Action — 매 PR diff scan.
# .gitleaks.toml[extend]useDefault=true[[rules]]id="acme-internal-token"description="Acme internal API token"regex='''ACME_[A-Z0-9]{32}'''keywords=["acme_"]entropy=3.5[[rules]]id="anthropic-api-key"description="Anthropic API key"regex='''sk-ant-[a-zA-Z0-9-_]{95,}'''keywords=["sk-ant-"][allowlist]description="test fixtures"paths=['''(.*?)tests/fixtures/.*''','''(.*?)\.example\..*''',]
매 GitHub Action (PR scan)
# .github/workflows/secrets-scan.ymlname:Secrets Scanon:[pull_request]jobs:gitleaks:runs-on:ubuntu-lateststeps:- uses:actions/checkout@v4with:fetch-depth:0# 매 full history 필요- uses:gitleaks/gitleaks-action@v2env:GITHUB_TOKEN:${{ secrets.GITHUB_TOKEN }}GITLEAKS_LICENSE:${{ secrets.GITLEAKS_LICENSE }}
매 trufflehog v3 (with verification, 매 live key 만 alert)
# 매 git history 전체 scan, 매 verified live key 만
$ trufflehog git file://. --only-verified --json | jq .
# 매 GitHub org scan
$ trufflehog github --org=acme --token=$GH_PAT --only-verified
# 매 Docker image scan
$ trufflehog docker --image=acme/api:latest --only-verified
매 leaked key remediation (매 4-step)
# 1. 매 ROTATE first (매 코드 수정 전!) — 매 leak 시 attacker timer 시작
aws iam create-access-key --user-name svc-deploy
aws iam delete-access-key --access-key-id AKIA... --user-name svc-deploy
# 2. 매 history rewrite (BFG, 매 git filter-repo 보다 빠름)
bfg --replace-text passwords.txt repo.git
cd repo.git && git reflog expire --expire=now --all && git gc --prune=now --aggressive
# 3. 매 force push (매 collaborator 들에게 reclone 공지)
git push --force-with-lease
# 4. 매 audit logs — 매 attacker 가 이미 사용했는지
aws cloudtrail lookup-events --lookup-attributes \
AttributeKey=AccessKeyId,AttributeValue=AKIA...
매 AI-aided false-positive triage (Claude Opus 4.7)
importanthropicclient=anthropic.Anthropic()deftriage(finding):"""gitleaks finding -> {is_real_secret, severity, action}"""prompt=f"""You are a security engineer. Decide if this is a real secret leak.
Finding:
File: {finding['file']} Line: {finding['line']} Match: {finding['match']} Context (5 lines before/after):
{finding['context']}Output JSON:
is_real_secret: bool
reason: str
severity: low|medium|high|critical
action: rotate|ignore|investigate
"""msg=client.messages.create(model="claude-opus-4-7",max_tokens=512,messages=[{"role":"user","content":prompt}],)returnmsg.content[0].text
매 GitHub Push Protection (매 enable, free for public)
# 매 org-level: Settings → Code security → Push protection: Enabled# 매 push 시 GitHub 가 server-side block — 매 partner pattern 매 200+ provider
gh api -X PATCH orgs/acme \
-F secret_scanning_push_protection_enabled_for_new_repositories=true
매 Doppler/Infisical (매 secret manager — 매 prevention root cause)
# 매 .env 의 X — 매 secret manager 에서 inject
$ doppler run -- python app.py
# 매 process env 에 inject, 매 disk 에 닿지 않음
언제: 매 finding triage (매 false positive vs real). 매 git history 의 narrative incident report.
언제 X: 매 detection 자체 — 매 deterministic regex/entropy 가 더 빠르고 cheap. 매 LLM 의 latency + cost 매 inline 부적절.
❌ 안티패턴
".env in repo": 매 매 the most common leak vector. 매 secret manager.
Commit-then-rotate skip: 매 rotate skip — 매 history forever.
.gitignore rely: 매 already-committed file 은 ignore 영향 X.
Force-push without coord: 매 collaborator 의 reflog 에 leak 잔존.
Public-key panic: 매 pub key 는 leak 의 X — 매 알고 commit.