---
name: owasp-security
description: "OWASP Top 10 (2021) 기반 보안 코드 리뷰 자동화. Python(FastAPI/Flask), TypeScript(Next.js), SQL(Firestore/PostgreSQL) 스택 특화. 보험/금융 도메인 PII 검사 포함."
triggers:
  - "owasp"
  - "보안 검사"
  - "security review"
  - "security audit"
  - "취약점 검사"
  - "보안 리뷰"
  - "vulnerability scan"
  - "보안 스캔"
usage: "/owasp-security [--quick|--full] [--path <dir>] [--output json|md]"
---

# /owasp-security — OWASP Top 10 기반 보안 코드 리뷰

> 출처: ComposioHQ/awesome-claude-skills Security & Systems 카테고리 참조
> 우리 시스템에 맞게 커스텀 (OWASP Top 10 2021 특화 신규 스킬, 보험/금융 도메인 항목 추가)

우리 시스템에 보안 스킬이 0개인 갭을 해소하기 위해 제작된 최우선 보안 스킬.
OWASP Top 10 (2021) 전체 체크리스트를 기반으로 코드베이스를 자동 스캔하고 취약점 보고서를 생성한다.

## User-invocable

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

## Arguments

- `/owasp-security` — 기본 (현재 디렉토리, `--quick` 모드)
- `/owasp-security --quick` — 10분 내 주요 취약점 검사 (A01/A02/A03/A05/A07 중심)
- `/owasp-security --full` — 전체 OWASP Top 10 항목 검사
- `/owasp-security --path /home/jay/projects/myapp` — 특정 디렉토리 지정
- `/owasp-security --output json` — JSON 형식 출력 (QC verifier 연동용)
- `/owasp-security --output md` — 마크다운 보고서 출력 (기본)
- `/owasp-security --full --path /home/jay/projects/myapp --output json` — 전체 옵션 조합

---

## Step 0: Pre-flight 확인

```bash
# 대상 경로 확인
ls -la <path> 2>/dev/null || echo "ERROR: 경로를 찾을 수 없습니다"

# 스택 탐지
find <path> -name "requirements.txt" -o -name "pyproject.toml" | head -5
find <path> -name "package.json" | head -5
find <path> -name "*.py" | head -3
find <path> -name "*.ts" -o -name "*.tsx" | head -3
```

- 경로가 없으면 중단.
- 스택 자동 탐지: Python (FastAPI/Flask), TypeScript (Next.js), SQL (Firestore/PostgreSQL).
- `--quick` 모드: A01, A02, A03, A05, A07 5개 항목만 검사.
- `--full` 모드: A01~A10 전체 10개 항목 검사.

---

## Step 1: OWASP Top 10 (2021) 체크리스트 스캔

### A01: Broken Access Control (접근 제어 오류)

**검사 방법**: Grep 패턴 매칭 + 수동 코드 리뷰

```bash
# 인가 검사 누락 탐지 (Python)
grep -r "def get_\|def post_\|def put_\|def delete_\|@app.route\|@router\." <path> --include="*.py" -l

# JWT/토큰 검증 없는 엔드포인트 탐지
grep -r "request.user\|current_user\|get_current_user" <path> --include="*.py" -n

# TypeScript: Next.js API route 인가 검사 누락
grep -r "export default\|export async function" <path> --include="*.ts" --include="*.tsx" -n
```

**체크 항목:**
- [ ] 모든 API 엔드포인트에 인증/인가 미들웨어 적용 여부
- [ ] 직접 객체 참조(IDOR): URL의 ID 값으로 다른 사용자 데이터 접근 가능 여부
- [ ] 관리자 기능에 role 체크 없이 접근 가능 여부
- [ ] CORS 설정 `allow_origins=["*"]` 남용 여부
- [ ] 보험/금융 특화: 약관/청구 데이터 조회 시 고객 본인 확인 로직 존재 여부

---

### A02: Cryptographic Failures (암호화 오류)

**검사 방법**: Grep 패턴 매칭

```bash
# 평문 민감 데이터 탐지
grep -rn "password\s*=\s*['\"]" <path> --include="*.py" --include="*.ts"
grep -rn "SECRET_KEY\s*=\s*['\"]" <path>
grep -rn "API_KEY\s*=\s*['\"]" <path>

# 취약 해시 함수 사용 탐지
grep -rn "md5\|sha1\b" <path> --include="*.py" --include="*.ts"

# HTTP (비암호화) 통신 탐지
grep -rn "http://" <path> --include="*.py" --include="*.ts" --include="*.env"
```

**체크 항목:**
- [ ] 비밀번호 bcrypt/argon2 해싱 여부 (MD5/SHA1 사용 금지)
- [ ] 민감 데이터(주민번호, 카드번호) 저장 시 암호화 여부
- [ ] HTTPS 강제 적용 여부 (HTTP redirect 포함)
- [ ] .env 파일에 하드코딩된 시크릿 키 여부
- [ ] 보험/금융 특화: PII(개인식별정보) — 주민등록번호, 계좌번호 평문 저장 여부

---

### A03: Injection (인젝션)

**검사 방법**: Grep 패턴 매칭 (SQL, XSS, Command)

```bash
# SQL Injection: f-string 또는 문자열 연결로 쿼리 생성 탐지
grep -rn "f\"SELECT\|f'SELECT\|\"SELECT.*\+\|execute(f\"\|execute(\".*%" <path> --include="*.py"

# XSS: React dangerouslySetInnerHTML 탐지
grep -rn "dangerouslySetInnerHTML" <path> --include="*.tsx" --include="*.ts"

# Command Injection: subprocess/os.system에 입력값 직접 전달
grep -rn "os\.system\|subprocess\.call\|subprocess\.run\|eval(" <path> --include="*.py" -n

# Firestore/NoSQL Injection 패턴
grep -rn "\.where(.*request\|\.where(.*params\|\.where(.*query" <path> --include="*.py" --include="*.ts"
```

**체크 항목:**
- [ ] SQL 쿼리: Parameterized Query / ORM 사용 여부 (raw query 금지)
- [ ] XSS: 사용자 입력값 HTML 렌더링 전 이스케이프 처리 여부
- [ ] Command Injection: os.system/subprocess에 사용자 입력 직접 전달 여부
- [ ] ORM (SQLAlchemy/TypeORM) 사용 시에도 raw query 혼용 여부
- [ ] 보험/금융 특화: 보험 약관 검색 쿼리에 인젝션 방어 여부

---

### A04: Insecure Design (불안전한 설계)

**검사 방법**: 코드 구조 분석 + 수동 리뷰

**체크 항목:**
- [ ] 비즈니스 로직 검증 부재 (예: 음수 보험금, 미래 날짜 청구)
- [ ] Rate limiting 미적용 (로그인, API 전반)
- [ ] 대량 할당(Mass Assignment) 취약점: 클라이언트 입력을 모델에 직접 바인딩
- [ ] 금액/수량 관련 로직에 서버측 재검증 없이 클라이언트 값 신뢰 여부
- [ ] 보험/금융 특화: 보험료 계산 로직 조작 가능 여부 (클라이언트 파라미터 변조)

```bash
# Mass Assignment 패턴 탐지 (Python)
grep -rn "\.update(request\.json\|\.update(\*\*request\.\|model\.\*\*dict" <path> --include="*.py"

# Rate limiting 설정 탐지
grep -rn "RateLimiter\|slowapi\|rate_limit\|throttle" <path> --include="*.py" --include="*.ts"
```

---

### A05: Security Misconfiguration (보안 설정 오류)

**검사 방법**: 설정 파일 + 코드 Grep

```bash
# 디버그 모드 프로덕션 배포 탐지
grep -rn "DEBUG\s*=\s*True\|debug=True\|NODE_ENV.*development" <path>

# 기본 자격증명 사용 탐지
grep -rn "admin.*admin\|root.*root\|password.*password\|secret.*secret" <path>

# CORS wildcard 탐지
grep -rn "allow_origins.*\*\|Access-Control-Allow-Origin.*\*" <path>

# 에러 메시지 상세 노출 탐지
grep -rn "traceback\|stack_trace\|exception.*str(e\|print(e)" <path> --include="*.py"

# 불필요한 HTTP 메서드 허용
grep -rn "methods=\[.*'TRACE'\|methods=\[.*'DELETE'" <path> --include="*.py"
```

**체크 항목:**
- [ ] DEBUG=True 프로덕션 배포 여부
- [ ] 기본 자격증명(admin/admin, root/root) 사용 여부
- [ ] 불필요한 HTTP 메서드 활성화 여부 (TRACE, OPTIONS)
- [ ] 에러 메시지에 스택 트레이스/내부 경로 노출 여부
- [ ] CORS 설정 과도하게 허용 여부
- [ ] 보안 헤더 누락 여부 (CSP, HSTS, X-Frame-Options)

---

### A06: Vulnerable and Outdated Components (취약하고 오래된 컴포넌트)

**검사 방법**: 의존성 파일 분석

```bash
# Python 의존성 확인
cat <path>/requirements.txt 2>/dev/null
cat <path>/pyproject.toml 2>/dev/null | grep -A 50 "\[tool.poetry.dependencies\]"

# Node.js 의존성 확인
cat <path>/package.json 2>/dev/null | python3 -m json.tool

# 취약 버전 패턴 확인 (예시)
grep -n "django\|flask\|fastapi\|sqlalchemy\|cryptography\|pyjwt" <path>/requirements.txt 2>/dev/null
grep -n "next\|react\|axios\|jsonwebtoken\|express" <path>/package.json 2>/dev/null
```

**체크 항목:**
- [ ] `requirements.txt` / `package.json` 버전 고정 여부 (`>=` 지양)
- [ ] 알려진 CVE 취약 버전 사용 여부 (주요 라이브러리 버전 확인)
- [ ] 더 이상 유지보수되지 않는(EOL) 라이브러리 사용 여부
- [ ] `pip audit` / `npm audit` 실행 결과 HIGH 이상 취약점 여부

```bash
# 취약점 스캔 (가능한 경우)
pip audit 2>/dev/null || echo "pip audit 미설치"
npm audit --json 2>/dev/null | python3 -m json.tool | head -50 || echo "npm audit 실행 불가"
```

---

### A07: Identification and Authentication Failures (인증 오류)

**검사 방법**: Grep 패턴 매칭 + 코드 리뷰

```bash
# JWT 검증 로직 탐지
grep -rn "jwt\.decode\|verify_token\|decode_access_token" <path> --include="*.py" -n

# 세션 만료 설정 탐지
grep -rn "access_token_expire\|SESSION_COOKIE_AGE\|PERMANENT_SESSION_LIFETIME\|expire" <path>

# 비밀번호 정책 탐지
grep -rn "password_validator\|validate_password\|min_length\|PasswordValidator" <path> --include="*.py"

# 브루트포스 방어 탐지
grep -rn "login_attempts\|lockout\|MAX_LOGIN_ATTEMPTS\|account_locked" <path>
```

**체크 항목:**
- [ ] JWT: `algorithm="none"` 허용 여부 (절대 금지)
- [ ] JWT 만료 시간 적절 여부 (access: 15분~1시간 권장)
- [ ] Refresh Token 안전한 저장 여부 (httpOnly cookie)
- [ ] 비밀번호 정책 적용 여부 (최소 8자, 복잡도)
- [ ] 로그인 실패 브루트포스 방어 (계정 잠금 또는 rate limiting)
- [ ] 보험/금융 특화: 금융 거래 시 추가 인증(2FA/OTP) 적용 여부

---

### A08: Software and Data Integrity Failures (소프트웨어 및 데이터 무결성 오류)

**검사 방법**: 코드 리뷰 + 설정 분석

```bash
# 서명 없는 패키지 설치 탐지 (CI/CD 파일)
find <path> -name "*.yml" -o -name "*.yaml" | xargs grep -l "pip install\|npm install" 2>/dev/null

# 역직렬화 위험 패턴 탐지
grep -rn "pickle\.loads\|yaml\.load(\|marshal\.loads" <path> --include="*.py"

# 동적 코드 실행 탐지
grep -rn "\beval(\|\bexec(\|__import__(" <path> --include="*.py"
```

**체크 항목:**
- [ ] `pickle.loads()` 신뢰할 수 없는 입력에 사용 여부
- [ ] `yaml.load()` 대신 `yaml.safe_load()` 사용 여부
- [ ] CI/CD 파이프라인에서 패키지 무결성 검증 여부 (hash/signature)
- [ ] 외부 CDN/스크립트 SRI(Subresource Integrity) 적용 여부
- [ ] 소프트웨어 업데이트 배포 시 서명 검증 여부

---

### A09: Security Logging and Monitoring Failures (보안 로깅 및 모니터링 오류)

**검사 방법**: 코드 리뷰 + 로깅 설정 분석

```bash
# 로깅 설정 탐지
grep -rn "import logging\|logger\s*=\|LOG_LEVEL\|structlog" <path> --include="*.py" -l
grep -rn "console\.log\|winston\|pino\|bunyan" <path> --include="*.ts" -l

# 민감 데이터 로그 출력 탐지 (위험 패턴)
grep -rn "logger.*password\|log.*token\|print.*ssn\|log.*주민" <path> --include="*.py"

# 보안 이벤트 로깅 탐지 (있어야 할 것)
grep -rn "login_failed\|access_denied\|unauthorized\|authentication_failure" <path> --include="*.py" --include="*.ts"
```

**체크 항목:**
- [ ] 로그인 실패, 인가 거부 이벤트 로깅 여부
- [ ] 로그에 비밀번호/토큰/주민번호 등 민감 데이터 출력 여부 (금지)
- [ ] 로그 레벨 적절 여부 (프로덕션에서 DEBUG 로그 과다 출력 금지)
- [ ] 로그 중앙화 및 이상 탐지 알림 설정 여부
- [ ] 보험/금융 특화: 보험 청구/조회/수정 이벤트 감사 로그(audit log) 여부

---

### A10: Server-Side Request Forgery (SSRF)

**검사 방법**: Grep 패턴 매칭

```bash
# 사용자 입력 URL로 HTTP 요청 탐지 (Python)
grep -rn "requests\.get\|requests\.post\|httpx\.get\|aiohttp" <path> --include="*.py" -n
grep -rn "urllib\.request\|urllib\.urlopen" <path> --include="*.py"

# TypeScript: 사용자 입력 URL fetch 탐지
grep -rn "fetch(\|axios\.get\|axios\.post" <path> --include="*.ts" --include="*.tsx" -n

# URL 검증 로직 탐지 (있어야 할 것)
grep -rn "urlparse\|validate_url\|is_safe_url\|allowed_hosts" <path> --include="*.py"
```

**체크 항목:**
- [ ] 사용자 입력 URL로 서버 측 HTTP 요청 시 whitelist 검증 여부
- [ ] 내부 네트워크 주소(169.254.x.x, 10.x.x.x, 172.16.x.x, 192.168.x.x) 접근 차단 여부
- [ ] `localhost`, `127.0.0.1` 요청 차단 여부
- [ ] Webhook URL 등록 시 도메인 검증 여부
- [ ] 보험/금융 특화: 외부 보험사 API 연동 URL의 whitelist 관리 여부

---

## Step 2: 보험/금융 도메인 특화 추가 검사

우리 서비스 특성에 맞는 추가 보안 항목:

```bash
# 주민등록번호 패턴 탐지 (평문 저장/로그 출력 금지)
grep -rn "[0-9]\{6\}-[0-9]\{7\}" <path> --include="*.py" --include="*.ts" --include="*.log"

# 카드번호 패턴 탐지
grep -rn "[0-9]\{4\}-[0-9]\{4\}-[0-9]\{4\}-[0-9]\{4\}" <path>

# 계좌번호 하드코딩 탐지
grep -rn "account_number\s*=\s*['\"][0-9]" <path>

# 보험 약관 데이터 접근 권한 체크 누락
grep -rn "policy\|insurance_data\|claim\|premium" <path> --include="*.py" -l
```

**추가 체크 항목:**
- [ ] 주민등록번호 평문 저장/전송/로그 출력 여부 (개인정보보호법 위반)
- [ ] 보험 청구 데이터 접근 시 계약자 본인 확인 로직 여부
- [ ] 보험료 계산 API 응답 조작 방지 (서버측 재계산)
- [ ] 고객 등급/혜택 데이터 직접 변조 가능 여부 (클라이언트 파라미터)
- [ ] 보험 약관 문서 다운로드 시 권한 검증 여부

---

## Step 3: 취약점 보고서 생성

### 마크다운 보고서 형식 (`--output md`, 기본)

```markdown
# 보안 코드 리뷰 보고서

**대상 경로**: /home/jay/projects/myapp
**검사 모드**: --full
**검사 일시**: 2026-04-12
**검사 항목**: OWASP Top 10 (2021) + 보험/금융 도메인 특화

---

## 요약

| 심각도 | 건수 |
|--------|------|
| CRITICAL | 1 |
| HIGH | 3 |
| MEDIUM | 2 |
| LOW | 4 |
| **합계** | **10** |

---

## 취약점 상세

### [CRITICAL] A02 - 암호화 오류: 주민등록번호 평문 저장

**파일**: `app/models/customer.py:45`
**심각도**: CRITICAL
**OWASP**: A02 - Cryptographic Failures

**증거 코드**:
\`\`\`python
# app/models/customer.py:45
customer.ssn = request.json["ssn"]  # 평문 저장 중
db.session.commit()
\`\`\`

**위험**: 개인정보보호법 위반. DB 유출 시 주민번호 즉시 노출.

**수정 권장**:
\`\`\`python
from cryptography.fernet import Fernet
customer.ssn = encrypt_pii(request.json["ssn"])  # 암호화 후 저장
\`\`\`

---

### [HIGH] A03 - SQL Injection: 보험 청구 조회 쿼리

**파일**: `app/api/claims.py:87`
**심각도**: HIGH
**OWASP**: A03 - Injection

**증거 코드**:
\`\`\`python
# app/api/claims.py:87
query = f"SELECT * FROM claims WHERE policy_id = {policy_id}"
db.execute(query)  # SQL Injection 취약
\`\`\`

**위험**: 공격자가 모든 고객의 보험 청구 데이터에 접근 가능.

**수정 권장**:
\`\`\`python
db.execute("SELECT * FROM claims WHERE policy_id = :pid", {"pid": policy_id})
\`\`\`
```

---

### JSON 보고서 형식 (`--output json`, QC verifier 연동)

```json
{
  "scan_meta": {
    "path": "/home/jay/projects/myapp",
    "mode": "full",
    "timestamp": "2026-04-12T10:30:00Z",
    "owasp_version": "2021",
    "stack": ["python", "fastapi", "postgresql"]
  },
  "summary": {
    "CRITICAL": 1,
    "HIGH": 3,
    "MEDIUM": 2,
    "LOW": 4,
    "total": 10,
    "pass": false
  },
  "vulnerabilities": [
    {
      "id": "OWASP-A02-001",
      "owasp_category": "A02",
      "owasp_name": "Cryptographic Failures",
      "severity": "CRITICAL",
      "file": "app/models/customer.py",
      "line": 45,
      "title": "주민등록번호 평문 저장",
      "description": "고객 주민등록번호가 암호화 없이 DB에 평문 저장됨",
      "evidence": "customer.ssn = request.json[\"ssn\"]",
      "recommendation": "AES-256 또는 Fernet으로 암호화 후 저장",
      "domain_tag": "PII"
    }
  ]
}
```

---

## Step 4: 심각도 기준 및 대응 SLA

| 심각도 | 기준 | 대응 기한 |
|--------|------|-----------|
| **CRITICAL** | 데이터 직접 유출 가능, PII 노출, 인증 우회 | 즉시 (당일) |
| **HIGH** | SQL Injection, 인가 오류, 암호화 미적용 | 48시간 이내 |
| **MEDIUM** | 보안 설정 오류, 로깅 누락, SSRF 위험 | 1주일 이내 |
| **LOW** | 잠재적 위험, 베스트 프랙티스 미준수 | 다음 스프린트 |

**CRITICAL 또는 HIGH 발견 시**: 즉시 팀장(아누)에게 보고 후 배포 중단.

---

## Quick 모드 vs Full 모드 비교

| 항목 | `--quick` (기본) | `--full` |
|------|-----------------|---------|
| 검사 시간 | ~10분 | ~30분 |
| 검사 항목 | A01, A02, A03, A05, A07 | A01~A10 전체 |
| 도메인 특화 검사 | 포함 (PII, 접근 제어) | 포함 (전체) |
| 권장 사용 시점 | PR 코드 리뷰 전, 빠른 점검 | 릴리즈 전, 정기 감사 |

---

## QC verifier 연동

`--output json` 으로 출력된 보고서를 QC verifier에 전달:

```bash
# JSON 보고서 생성
/owasp-security --full --output json > security-report.json

# QC verifier에서 CRITICAL/HIGH 여부 확인
python3 -c "
import json
report = json.load(open('security-report.json'))
critical_high = [v for v in report['vulnerabilities'] if v['severity'] in ['CRITICAL', 'HIGH']]
if critical_high:
    print(f'BLOCK: {len(critical_high)}건의 고위험 취약점 발견')
    exit(1)
else:
    print('PASS: 고위험 취약점 없음')
"
```

---

## Important Rules

- **CRITICAL/HIGH 발견 시 배포 즉시 중단.** 팀장(아누) 보고 필수.
- **PII(주민번호, 계좌번호) 발견 시 무조건 CRITICAL 처리.** 개인정보보호법 대상.
- **False Positive 판단 시** 해당 항목에 `// owasp-ignore: A03 <사유>` 주석 추가 후 재검사.
- **보안 보고서는 내부 문서로 관리.** 외부 공유 금지.
- **정기 스캔 권장**: 스프린트 릴리즈 전 `--full` 모드 1회 이상.
- **이 스킬은 자동화 도구를 대체하지 않는다.** Snyk, SonarQube 등 전문 도구와 병행 사용 권장.

---

**스킬 버전**: v1.0
**작성일**: 2026-04-12
**출처**: ComposioHQ/awesome-claude-skills Security & Systems 참조, OWASP Top 10 2021 특화 신규 제작
**담당**: 스바로그 (백엔드), 개발6팀
