보안
다운로드 후
~/.claude/rules/ 폴더에 복사하여 사용하세요모든 코드에 적용되는 필수 보안 규칙입니다.
🔒
보안은 선택 사항이 아닙니다. 모든 커밋 전에 보안 체크리스트를 확인하세요!
필수 보안 검사
모든 커밋 전:
- 하드코딩된 시크릿 없음 (API 키, 비밀번호, 토큰)
- 모든 사용자 입력 검증됨
- SQL 인젝션 방지 (파라미터화된 쿼리)
- XSS 방지 (HTML 새니타이즈)
- CSRF 보호 활성화
- 인증/인가 검증됨
- 모든 엔드포인트에 레이트 리미팅
- 오류 메시지가 민감한 데이터 노출하지 않음
시크릿 관리
// ❌ 절대 금지: 하드코딩된 시크릿
const apiKey = "sk-proj-xxxxx"
// ✅ 항상: 환경 변수
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) {
throw new Error('OPENAI_API_KEY가 설정되지 않았습니다')
}시크릿 패턴
| 패턴 | 설명 | 예시 |
|---|---|---|
sk-* | API 키 | sk-proj-abc123 |
ghp_* | GitHub 토큰 | ghp_xxx... |
Bearer * | 인증 토큰 | Bearer eyJ... |
SQL 인젝션 방지
// ❌ 위험: 문자열 연결
const query = `SELECT * FROM users WHERE id = ${userId}`
// ✅ 안전: 파라미터화된 쿼리
const { data } = await supabase
.from('users')
.select('*')
.eq('id', userId)XSS 방지
// ❌ 위험: innerHTML 직접 사용
element.innerHTML = userInput
// ✅ 안전: textContent 사용
element.textContent = userInput
// ✅ 안전: 라이브러리로 새니타이즈
import DOMPurify from 'dompurify'
element.innerHTML = DOMPurify.sanitize(userInput)입력 검증
import { z } from 'zod'
const userSchema = z.object({
email: z.string().email(),
password: z.string().min(8).max(100),
age: z.number().int().min(0).max(150)
})
// 검증 실패 시 예외 발생
const validatedUser = userSchema.parse(input)보안 대응 프로토콜
보안 이슈 발견 시:
- 즉시 중단 - 코드 작성 중지
- security-reviewer 에이전트 사용 - 전체 분석
- CRITICAL 이슈 수정 - 계속하기 전에 해결
- 시크릿 로테이션 - 노출된 시크릿 교체
- 전체 검토 - 유사한 이슈가 있는지 코드베이스 검토
보안 등급
| 등급 | 설명 | 조치 |
|---|---|---|
| 🔴 치명적 | 시크릿 노출, 인젝션 | 즉시 수정 필수 |
| 🟠 높음 | 인증 우회, XSS | 커밋 전 수정 |
| 🟡 중간 | 레이트 리미팅 누락 | 가능한 빨리 수정 |
| 🟢 낮음 | 정보 노출 가능성 | 검토 후 수정 |