왜 시크릿 유출이 치명적인가
API 키, DB 비밀번호, 클라우드 액세스 키가 Git 히스토리에 한 번 커밋되면, 이후 커밋에서 삭제하더라도 히스토리에는 영원히 남는다. 공개 저장소라면 자동화된 봇이 수 분 내에 스캔해 탈취하고, 비공개 저장소라도 협력사·퇴사자·포크를 통해 노출 범위가 넓어진다. 유출된 키는 암호화폐 채굴, 데이터 유출, 램섬웨어의 초기 진입점이 된다. 핵심은 "커밋된 뒤 대응"이 아니라 "머지되기 전에 차단"이다.
gitleaks란
gitleaks는 정규식 규칙과 엔트로피 기반 휴리스틱으로 소스와 Git 히스토리에서 자격증명 패턴을 찾아내는 오픈소스 도구다. 단일 바이너리로 배포되어 CI에 넣기 쉽고, 규칙을 TOML로 커스터마이징할 수 있다. 사용 지점은 크게 세 곳이다: 개발자 로컬(pre-commit), PR 검사(CI), 그리고 이미 머지된 히스토리 전수 스캔.
CI에 통합하기 (GitHub Actions)
PR에서 새로 추가된 커밋만 스캔하면 빠르고, 기존 히스토리 전체를 스캔하려면 fetch-depth: 0으로 전체 이력을 받아야 한다. 스캔에서 하나라도 걸리면 종료 코드 1로 파이프라인을 실패시킨다.
name: secret-scan
on: [pull_request]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 전체 히스토리 스캔
- name: Run gitleaks
run: |
curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.18.4/gitleaks_8.18.4_linux_x64.tar.gz \
| tar -xz gitleaks
./gitleaks detect --source . --redact -v \
--report-format sarif --report-path results.sarif
--redact는 로그에 실제 시크릿 값이 노출되지 않도록 마스킹한다. 이 옵션 없이 돌리면 CI 로그 자체가 2차 유출 경로가 되므로 반드시 켠다.
로컬에서 먼저 막기 (pre-commit)
CI에서만 막으면 개발자는 이미 커밋을 만든 뒤에야 실패를 알게 된다. pre-commit 훅으로 커밋 시점에 차단하면 히스토리 오염 자체를 예방할 수 있다.
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaks
pre-commit install 한 번이면 매 커밋마다 자동 실행된다. 다만 훅은 개발자가 --no-verify로 우회할 수 있으므로 CI 검사를 최종 방어선으로 반드시 둔다.
오탐 관리와 규칙 커스터마이징
테스트 픽스처의 가짜 키, 예시 문서의 더미 값은 오탐을 만든다. 무작정 규칙을 끄기보다 특정 항목만 허용 목록에 넣는다. 허용 처리는 반드시 리뷰 대상이어야 하며, 실제 키를 실수로 예외 처리하지 않도록 주의한다.
# .gitleaks.toml
[allowlist]
description = "테스트 및 문서 예외"
paths = [
'''tests/fixtures/.*''',
'''docs/examples/.*''',
]
regexes = [
'''EXAMPLE_[A-Z0-9]{16}''',
]
스캔 방식 비교
| 지점 | 차단 시점 | 우회 가능성 | 비고 |
|---|---|---|---|
| pre-commit | 커밋 전 | 높음(--no-verify) | 개발자 경험 최선 |
| CI(PR) | 머지 전 | 낮음 | 필수 방어선 |
| 히스토리 전수 | 사후 탐지 | - | 정기 감사용 |
유출 발견 후 대응
스캔이 진짜 키를 잡았다면 히스토리에서 지우는 것만으로는 부족하다. 노출된 순간 그 키는 이미 유효하지 않다고 간주하고 즉시 폐기·회전(rotate)해야 한다. 순서는 (1) 해당 키 비활성화, (2) 새 키 발급 및 배포, (3) 접근 로그로 오용 여부 확인, (4) 필요 시 git filter-repo로 히스토리 정리다. 히스토리 재작성은 강제 푸시와 협업자 재클론을 유발하므로 회전을 먼저 끝내는 것이 원칙이다.
정리
시크릿 스캔은 "커밋 전 → 머지 전 → 정기 감사"의 다층 방어로 구성할 때 실효성이 있다. pre-commit으로 개발자 편의를, CI 필수 검사로 강제력을, 히스토리 전수 스캔으로 사각지대를 메운다. 무엇보다 스캔 도입과 함께 "노출된 키는 즉시 회전한다"는 운영 원칙을 팀 프로세스로 못 박아야 도구가 제 역할을 한다.