# InsuRo 보안 취약점 수정 — CRITICAL 2건 + HIGH 6건

## 작업 레벨: Lv.3

## 프로젝트 시스템 3문서
- DevSystem: `/home/jay/workspace/memory/plans/anu-guide-system/plan.md`

## 프로젝트
- InsuRo: `/home/jay/projects/InsuRo`
- 서버: `/home/jay/projects/InsuRo/server`

## 참고: 보안 감사 상세 보고서
- `/home/jay/workspace/memory/reports/insuro-security-audit-2026-04.md` 반드시 읽을 것

## 수정 사항 (8건)

### CRITICAL 1: SSRF — file_url 무검증 다운로드
**파일**: `server/main.py:4076`
URL 화이트리스트 검증 함수 `_validate_file_url()` 추가:
- HTTPS만 허용
- 허용 도메인: supabase.co, drive.google.com, storage.googleapis.com
- 내부 IP(private/loopback/link-local) 차단
- 검증 실패 시 400 에러

### CRITICAL 2: .env 시크릿 보호 강화
- `.env` 파일 퍼미션 600 확인
- 코드에 시크릿 하드코딩이 없는지 전수 확인 (grep으로 검증)
- 로그에 시크릿 출력되는 곳 없는지 확인

### HIGH 1: JWT verify_signature:False 수정
**파일**: `server/main.py:225-229`
다중 계정 탐지 미들웨어에서 서명 미검증 → 검증 후 사용 또는 검증 실패 시 탐지 스킵.

### HIGH 2: JWT verify_aud:False 수정
**파일**: `server/main.py:670-675`
`audience` 파라미터 명시적 설정 (Supabase 프로젝트 ref).

### HIGH 3: npm audit fix
`npm audit fix` 실행하여 HIGH 취약점 14건 해결. breaking change 있으면 수동 확인.

### HIGH 4: 에러 메시지 일반화 (11개소)
보고서에 명시된 11개 파일/라인에서 `detail=str(exc)` → `detail="일시적인 오류가 발생했습니다."` + `logger.exception()` 추가.
대상: main.py:1480, 4468, 4616, 1920, 2719 + mediscan_router.py:223 + generation_queue.py:67,74 + pipeline.py:138 + image_generator.py:100

### HIGH 5: subprocess 입력 검증
**파일**: main.py:3685, 3712, 3874, 3935, 4034
파일 경로 정규표현식 화이트리스트 검증 함수 추가. 특수문자 포함 시 거부.

### HIGH 6: 파일 변환 엔드포인트 인증/Rate Limit
**파일**: main.py:3327, 3431
`/api/tools/convert/word-to-pdf`, `/api/tools/convert/pdf-to-word`에:
- `@limiter.limit("10/minute")` 추가
- `Depends(verify_jwt)` 추가

## affected_files
- `server/main.py` (수정 — SSRF, JWT, 에러 메시지, subprocess, rate limit)
- `server/mediscan_router.py` (수정 — 에러 메시지)
- `server/generation_queue.py` (수정 — 에러 메시지)
- `server/pipeline.py` (수정 — 에러 메시지)
- `server/image_generator.py` (수정 — 에러 메시지)
- `package.json` / `package-lock.json` (수정 — npm audit fix)

## 검증 시나리오
1. SSRF: 내부 IP URL 요청 → 400 거부
2. JWT: verify_aud 활성화 후 정상 로그인 가능
3. 에러: 500 에러 시 "일시적인 오류" 메시지만 반환 (스택트레이스 없음)
4. npm audit: HIGH 0건
5. 파일 변환: 인증 없이 접근 → 401
6. pytest 전량 통과
7. npm run build 성공
