---
name: sanitize
description: "코드/문서/로그에서 한국 PII(개인식별정보)를 자동 탐지하고 마스킹한다. 보험/금융 도메인 특화 (주민등록번호, 계좌번호, 보험 증권번호 등)."
triggers:
  - "sanitize"
  - "PII"
  - "개인정보"
  - "개인식별정보"
  - "마스킹"
  - "masking"
  - "주민등록번호"
  - "계좌번호"
  - "전화번호 노출"
  - "개인정보 스캔"
  - "민감정보"
  - "보험 증권번호"
  - "카드번호"
  - "여권번호"
  - "운전면허"
  - "외국인등록번호"
usage: "/sanitize [--path <경로>] [--report | --mask | --fix]"
---

# /sanitize — 한국 PII 탐지 및 마스킹

> 출처: 커스텀 스킬 (보험/금융 도메인 특화, 개발2팀 토르 작성)
> owasp-security 스킬과 보완적 관계: owasp-security는 보안 취약점(인젝션, XSS 등) 탐지, sanitize는 PII 데이터 탐지 전용.

코드, 문서, 로그 파일에서 한국형 PII를 grep 패턴으로 스캔하여 위험도를 분류하고, 선택적으로 마스킹한다. 보험/금융 시스템에서 민감 데이터가 소스코드나 로그에 유출되는 것을 방지하는 데 특화되어 있다.

**토르(개발2팀 백엔드 전문가)** 가 이 스킬을 주도한다.

---

## User-invocable

사용자가 `/sanitize`를 입력하면 이 스킬을 실행한다.

---

## Arguments

- `/sanitize` — 현재 작업 디렉토리 전체 스캔 (보고서 모드)
- `/sanitize --path <경로>` — 특정 파일 또는 디렉토리 지정
- `/sanitize --report` — 발견 결과만 보고, 파일 수정 없음 (기본값)
- `/sanitize --mask` — 발견된 PII를 `***`로 자동 일괄 마스킹
- `/sanitize --fix` — 인터랙티브 모드: 발견 건별로 확인 후 마스킹 여부 결정

---

## 절대 규칙

> **이 규칙은 어떤 상황에서도 예외 없이 적용된다.**

1. **`--mask` 또는 `--fix` 없이 파일 수정 금지**: `--report`(기본값)로 실행 시 어떤 파일도 수정하지 않는다.
2. **`.env`, `.git`, `node_modules` 기본 제외**: 이 경로들은 별도 지정이 없는 한 스캔 대상에서 제외한다.
3. **마스킹 전 백업 안내 필수**: `--mask` 실행 전 "git commit 또는 백업 후 진행을 권장합니다"를 반드시 출력한다.
4. **오탐 경고 표시**: 테스트/목업 데이터 파일(`test_`, `mock_`, `fixture_` 패턴)에서 발견 시 `[오탐 가능]` 표시.

---

## 워크플로우 개요

```
Step 1: 환경 확인 및 스캔 대상 결정
    ↓
Step 2: PII 패턴 grep 스캔 실행
    ↓
Step 3: 발견 결과 위험도 분류 및 보고
    ↓
Step 4: 마스킹 옵션 실행 (--report면 종료)
    ↓
Step 5: 마스킹 결과 검증
```

---

## Step 1: 환경 확인 및 스캔 대상 결정

### 1.1 스캔 대상 경로 확인

```bash
# 기본: 현재 작업 디렉토리
SCAN_PATH="${PWD}"

# --path 지정 시 해당 경로 사용
# SCAN_PATH="<지정된 경로>"

# 제외 경로 (기본값)
EXCLUDE_PATHS=(".git" "node_modules" ".env" "*.lock" "*.log.gz" "dist/" "build/")
```

### 1.2 스캔 전 출력 형식

```
## [sanitize] 스캔 준비

스캔 대상: <경로>
모드: <report / mask / fix>
제외 경로: .git, node_modules, .env, *.lock

스캔을 시작합니다...
```

---

## Step 2: PII 패턴 스캔

### 2.1 한국 PII grep 패턴 목록

아래 패턴을 순서대로 스캔한다.

#### CRITICAL 등급 패턴

```bash
# 주민등록번호 (내국인): 900101-1234567
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '\d{6}-?[1-4]\d{6}' "$SCAN_PATH"

# 외국인등록번호: 900101-5234567
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '\d{6}-?[5-8]\d{6}' "$SCAN_PATH"

# 카드번호 (16자리): 1234-5678-9012-3456
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '\d{4}-?\d{4}-?\d{4}-?\d{4}' "$SCAN_PATH"
```

#### HIGH 등급 패턴

```bash
# 계좌번호 (주요 은행 패턴): 110-123456-12
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '\d{3,4}-?\d{2,6}-?\d{2,6}' "$SCAN_PATH"

# 여권번호: M12345678
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '[A-Z]\d{8}' "$SCAN_PATH"

# 운전면허번호: 11-22-333333-44
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '\d{2}-\d{2}-\d{6}-\d{2}' "$SCAN_PATH"

# 보험 증권번호: AB12345678 ~ ABCD123456789012
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '[A-Z]{2,4}\d{8,12}' "$SCAN_PATH"
```

#### MEDIUM 등급 패턴

```bash
# 전화번호 (휴대폰): 010-1234-5678
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '01[016789]-?\d{3,4}-?\d{4}' "$SCAN_PATH"

# 이메일 주소
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E '[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}' "$SCAN_PATH"
```

#### 보험/금융 도메인 특화 패턴

```bash
# 건강보험 자격득실확인서 번호 패턴 (숫자 12~14자리 연속)
grep -rn --include="*.{py,js,ts,java,go,json,yaml,yml,txt,log,sql,csv,xml,html,md}" \
  -E 'health_no|insure_no|cert_no|자격득실|피보험자번호' "$SCAN_PATH"
```

### 2.2 스캔 제외 조건

- 경로에 `.git/`, `node_modules/`, `dist/`, `build/` 포함 시 제외
- `.env`, `.env.local`, `.env.production` 파일: 별도 경고와 함께 보고 (자동 수정 대상 아님)
- 바이너리 파일 (`.png`, `.jpg`, `.pdf`, `.zip` 등) 제외

---

## Step 3: 발견 결과 보고

### 3.1 위험도 분류 기준

| 등급 | 유형 | 설명 |
|------|------|------|
| CRITICAL | 주민등록번호, 외국인등록번호, 카드번호 | 즉시 조치 필요. 금융감독원 규정 위반 소지. |
| HIGH | 계좌번호, 여권번호, 운전면허, 보험 증권번호 | 우선 마스킹 권장. |
| MEDIUM | 전화번호, 이메일 | 상황에 따라 마스킹. 로그/테스트 파일 주의. |
| LOW | 이름 패턴 (오탐 가능성 높음) | 수동 확인 권장. |

### 3.2 발견 결과 출력 형식

```
## PII 스캔 결과

스캔 경로: <경로>
스캔 시각: <YYYY-MM-DD HH:MM:SS>
총 발견: <N>건 (CRITICAL: X, HIGH: X, MEDIUM: X)

| # | 파일 | 라인 | 유형 | 등급 | 내용 (일부 마스킹) |
|---|------|------|------|------|--------------------|
| 1 | data/users.json | 15 | 주민등록번호 | CRITICAL | 900101-1****** |
| 2 | logs/api.log | 42 | 전화번호 | MEDIUM | 010-****-5678 |
| 3 | src/test_data.py | 8 | 계좌번호 | HIGH | 110-1****-12 [오탐 가능] |

---

### 위험도별 요약

**CRITICAL (<N>건)** — 즉시 조치 권장
- <파일:라인>: <유형>

**HIGH (<N>건)** — 우선 마스킹 권장
- <파일:라인>: <유형>

**MEDIUM (<N>건)** — 검토 후 조치
- <파일:라인>: <유형>

---

### 보험/금융 도메인 주의사항

- 보험 증권번호, 청구번호가 API 응답 로그에 포함된 경우 → 로그 마스킹 설정 추가 권장
- .env 파일에서 발견된 경우 → git 히스토리 정리 필요 (git-filter-repo 활용)
- 테스트 데이터 파일에서 발견된 경우 → 실제 PII 사용 금지, faker 라이브러리로 대체 권장

---

다음 중 선택하세요:
- 마스킹: `/sanitize --mask` (자동 일괄 마스킹)
- 건별 확인: `/sanitize --fix` (인터랙티브 마스킹)
- 종료: 이 보고서를 저장하고 수동 처리
```

---

## Step 4: 마스킹 실행

### 4.1 --mask 모드 (자동 일괄 마스킹)

마스킹 전 반드시 아래 경고를 출력한다:

```
[경고] --mask 모드는 발견된 모든 PII를 *** 로 대체합니다.
git commit 또는 파일 백업 후 진행을 강력히 권장합니다.
계속하시겠습니까? (yes/no)
```

마스킹 적용 규칙:
- 주민등록번호: `900101-1234567` → `900101-*******`
- 전화번호: `010-1234-5678` → `010-****-5678`
- 카드번호: `1234-5678-9012-3456` → `****-****-****-3456`
- 계좌번호: `110-123456-12` → `110-******-**`
- 이메일: `user@example.com` → `us**@example.com`
- 여권번호: `M12345678` → `M*******8`
- 보험 증권번호: `AB12345678` → `AB****5678`

```bash
# sed 기반 마스킹 예시 (주민등록번호)
sed -i -E 's/([0-9]{6})-?([1-4][0-9]{6})/\1-*******/g' "<파일경로>"
```

### 4.2 --fix 모드 (인터랙티브 마스킹)

발견 건별로 아래 형식으로 확인을 요청한다:

```
[1/5] 파일: data/users.json, 라인 15
      유형: 주민등록번호 (CRITICAL)
      내용: "resident_no": "900101-1234567"
      마스킹하시겠습니까? (y/n/skip):
```

---

## Step 5: 마스킹 결과 검증

마스킹 완료 후 동일 패턴으로 재스캔하여 잔여 PII 여부를 확인한다.

```
## [sanitize] 마스킹 완료

처리된 파일: <N>개
마스킹된 항목: <N>건
잔여 발견 건수: 0건 (검증 완료)

저장 경로: <원본 파일 경로> (원본 덮어쓰기)

---
git diff 로 변경사항을 확인하고 커밋하세요.
```

---

## 보험/금융 도메인 특화 가이드

### PII 유형별 규제 맥락

| PII 유형 | 관련 규정 | 조치 우선순위 |
|----------|-----------|--------------|
| 주민등록번호 | 개인정보보호법 제24조, 금융실명법 | 즉시 (CRITICAL) |
| 계좌번호 | 금융실명법, 전기통신금융사기방지법 | 높음 (HIGH) |
| 보험 증권번호 | 보험업법, 개인정보보호법 | 높음 (HIGH) |
| 카드번호 | PCI-DSS, 여신전문금융업법 | 즉시 (CRITICAL) |
| 전화번호 | 개인정보보호법 제15조 | 중간 (MEDIUM) |

### 자주 발생하는 PII 유출 패턴 (보험 시스템)

1. **API 응답 로그**: 보험 청구 API 응답 전문을 그대로 로그로 저장하는 경우
2. **DB 덤프 파일**: 개발/테스트용 DB 덤프에 실제 고객 데이터 포함
3. **에러 스택트레이스**: 에러 메시지에 요청 파라미터(주민번호 등) 포함
4. **설정 파일**: `application.yml`, `config.json`에 테스트 계정 정보 하드코딩
5. **커밋 히스토리**: git log에 PII 포함 파일이 한 번이라도 커밋된 경우

### owasp-security 스킬과의 역할 분담

| 스킬 | 탐지 대상 | 사용 시점 |
|------|-----------|----------|
| owasp-security | SQL 인젝션, XSS, 인증 취약점, 시크릿 키 노출 | 코드 보안 리뷰 시 |
| sanitize | 주민번호, 계좌번호, 전화번호 등 PII 데이터 | 배포 전 데이터 검증, 로그 점검 |

두 스킬을 함께 실행하면 보안 + 개인정보보호 전체 커버리지 확보 가능.

---

## 빠른 참조

```bash
# 현재 디렉토리 전체 스캔 (보고서만)
/sanitize

# 특정 경로 스캔
/sanitize --path src/

# 자동 마스킹
/sanitize --mask

# 보고서만 (수정 없음)
/sanitize --report

# 인터랙티브 마스킹
/sanitize --fix
```

---

## 금지사항

1. **`--report` 모드에서 파일 수정 금지** — 보고서 출력만 허용한다.
2. **`.env` 파일 자동 마스킹 금지** — 별도 경고 후 사용자가 직접 처리한다.
3. **마스킹 전 경고 생략 금지** — 항상 백업 권장 메시지를 출력한다.
4. **오탐을 확정 PII로 처리 금지** — 테스트/목업 파일은 `[오탐 가능]` 표시 후 사용자 판단에 맡긴다.
5. **git 히스토리 자동 수정 금지** — 히스토리 정리는 사용자에게 안내만 한다 (git-filter-repo 등).

---

**스킬 버전**: v1.0
**작성일**: 2026-04-12
**작성자**: 토르 (개발2팀 백엔드 전문가)
**출처**: 커스텀 스킬 (보험/금융 도메인 특화, 한국 PII 패턴 기반)
**참조**: owasp-security SKILL.md, 개인정보보호법, 금융감독원 IT 보안 가이드라인
