--- description: Comprehensive security scanning for secrets, vulnerabilities, and code issues --- # Security Checker 프로젝트의 보안 취약점을 포괄적으로 검사합니다. 환경 변수 노출, 하드코딩된 시크릿, 의존성 취약점, 코드 보안 이슈 등을 자동으로 탐지합니다. ## Steps to follow: ### 1. 민감 정보 노출 검사 (최우선 순위) 보안에서 가장 중요한 부분입니다. 철저하게 검사하세요. #### A. .gitignore 검증 **1단계: .gitignore 파일 읽기** - Read 도구로 `.gitignore` 파일 내용 확인 - 파일이 없으면 경고 **2단계: 필수 항목 확인** 다음 항목이 포함되어 있는지 체크: ``` .env .env.local .env.development .env.production .env.*.local node_modules/ .DS_Store Thumbs.db *.log *.key *.pem credentials.json secrets.json config/secrets.* .aws/ .gcloud/ ``` **누락된 항목은 경고로 표시** #### B. 환경 변수 파일 검사 **검색할 파일들:** ``` .env .env.local .env.development .env.production .env.test .env.staging ``` **Glob 도구로 검색:** ``` **/.env* ``` **각 파일에 대해:** 1. 파일이 존재하는지 확인 2. .gitignore에 포함되어 있는지 확인 3. **매우 중요**: Git 히스토리에 커밋된 적이 있는지 확인 ```bash git log --all --full-history -- .env ``` 결과가 있으면 **심각한 보안 문제**: - 언제 커밋되었는지 - 어떤 커밋 해시인지 - 조치 방법 안내 (git filter-branch) #### C. 하드코딩된 시크릿 탐지 **Grep 도구로 전체 프로젝트 검색** (node_modules, .git 제외) 다음 패턴들을 검색: **1. API 키 패턴:** ```regex (api[_-]?key|apikey|api[_-]?secret)\s*[:=]\s*['""][^'""]{20,}['""] ``` **2. AWS 키:** ```regex AKIA[0-9A-Z]{16} ``` **3. Private 키:** ```regex -----BEGIN (RSA |EC |DSA )?PRIVATE KEY----- ``` **4. 데이터베이스 연결 문자열 (비밀번호 포함):** ```regex (mongodb|postgresql|mysql):\/\/[^:]+:[^@]+@ ``` **5. 패스워드 하드코딩:** ```regex (password|passwd|pwd)\s*[:=]\s*['""][^'""]+['""] ``` **6. 토큰:** ```regex (token|bearer|jwt)\s*[:=]\s*['""][^'""]{20,}['""] ``` **7. GitHub 토큰:** ```regex gh[pousr]_[A-Za-z0-9_]{36,} ``` **8. Stripe 키:** ```regex (sk|pk)_(test|live)_[A-Za-z0-9]{24,} ``` **9. Google API 키:** ```regex AIza[0-9A-Za-z_-]{35} ``` **10. Slack 토큰:** ```regex xox[baprs]-[0-9]{10,12}-[0-9]{10,12}-[A-Za-z0-9]{24,} ``` **각 매칭에 대해:** - 파일 경로와 라인 번호 기록 - 매칭된 내용 (일부 마스킹) - 심각도: 매우 높음 **예외 처리:** - 주석 내용은 낮은 우선순위 - 테스트 파일 (`*.test.js`, `*.spec.js`)은 표시하되 우선순위 낮춤 - `example`, `placeholder`, `your-key-here` 같은 명확한 예시는 제외 #### D. Git 히스토리 검사 **민감한 키워드가 과거 커밋에 있는지 검사:** ```bash git log -p | grep -iE "(password|api.key|secret|token|bearer|private.key)" | head -50 ``` **발견되면:** - 어떤 커밋에서 발견되었는지 - 파일명 - **경고**: 이미 Git 히스토리에 기록되었으므로 단순 삭제로는 부족 - 조치 방법: ```bash # BFG Repo-Cleaner 사용 권장 bfg --delete-files .env git reflog expire --expire=now --all git gc --prune=now --aggressive ``` ### 2. 의존성 보안 검사 #### A. package.json 확인 **1단계: package.json 읽기** - Read 도구로 `package.json` 파일 읽기 - dependencies와 devDependencies 확인 **2단계: npm audit 실행** ```bash npm audit --json ``` **결과 분석:** - **Critical**: 즉시 수정 필요 - **High**: 빠른 시일 내 수정 - **Moderate**: 수정 권장 - **Low**: 주시 필요 **각 취약점에 대해:** - 패키지 이름 - 현재 버전 - 취약점 설명 - 권장 버전 - 수정 방법 **3단계: 오래된 패키지 확인** ```bash npm outdated ``` **Major 버전이 뒤쳐진 패키지 표시** #### B. 의존성 라이선스 확인 (선택적) 위험한 라이선스 (GPL 등) 체크 ### 3. 코드 보안 취약점 검사 #### A. SQL Injection 위험 **위험한 패턴 검색 (Grep):** ```regex (query|execute)\s*\(\s*['""`].*\$\{.*\}.*['""`] (query|execute)\s*\(\s*['""].*\+.*['""] ``` **구체적 예시:** ```javascript // 위험 db.query("SELECT * FROM users WHERE id = " + userId) db.query(`DELETE FROM ${table} WHERE id = ${id}`) // 안전 db.query("SELECT * FROM users WHERE id = ?", [userId]) db.query("SELECT * FROM users WHERE id = $1", [userId]) ``` **발견된 각 케이스:** - 파일 및 라인 번호 - 위험한 코드 - 안전한 대체 코드 제안 - 심각도: 높음 #### B. XSS (Cross-Site Scripting) 취약점 **위험한 패턴 검색:** ```regex \.innerHTML\s*= dangerouslySetInnerHTML document\.write\( eval\( ``` **구체적 예시:** ```javascript // 위험 element.innerHTML = userInput
document.write(input) // 안전 element.textContent = userInput DOMPurify.sanitize(userInput) ``` **심각도: 중간-높음** #### C. Command Injection **위험한 패턴:** ```regex exec\([^)]*\$\{ spawn\([^)]*\+ child_process.*\$\{ ``` **구체적 예시:** ```javascript // 위험 exec(`rm -rf ${userInput}`) spawn('sh', ['-c', command + userInput]) // 안전 execFile('rm', ['-rf', userInput]) // 인자를 배열로 ``` **심각도: 매우 높음** #### D. Path Traversal **위험한 패턴:** ```regex (readFile|writeFile|sendFile)\([^)]*\+ (readFile|writeFile|sendFile)\([^)]*\$\{ ``` **구체적 예시:** ```javascript // 위험 fs.readFile(req.query.file) res.sendFile(userPath) // 안전 const safePath = path.join(__dirname, 'uploads', path.basename(filename)) fs.readFile(safePath) ``` **심각도: 높음** #### E. 정규식 ReDoS (Regular Expression Denial of Service) **위험한 패턴:** - 중첩된 반복: `(a+)+` - 백트래킹이 과도한 패턴 ```regex \(\.\*\)\+ \(\.\+\)\+ ``` **심각도: 중간** ### 4. 설정 보안 검사 #### A. CORS 설정 **파일 검색:** - Express: `cors()` - 다른 프레임워크의 CORS 설정 **위험한 설정 검색:** ```regex cors\(\s*\{\s*origin:\s*['"]\*['""] Access-Control-Allow-Origin:\s*\* ``` **발견 시:** - 파일 및 위치 - 현재 설정 - 권장 설정: ```javascript // 안전한 설정 cors({ origin: ['https://yourdomain.com', 'https://app.yourdomain.com'] }) ``` **심각도: 중간** #### B. 보안 헤더 확인 **검색할 헤더:** - `helmet` 패키지 사용 여부 - 수동 헤더 설정 여부 **확인할 헤더:** 1. **X-Frame-Options**: Clickjacking 방지 2. **Content-Security-Policy**: XSS 방지 3. **X-Content-Type-Options**: MIME 스니핑 방지 4. **Strict-Transport-Security**: HTTPS 강제 5. **X-XSS-Protection**: XSS 필터 **package.json에서 helmet 검색:** - 없으면 권장 **서버 파일에서 헤더 설정 검색:** ```regex setHeader\(['""]X-Frame-Options setHeader\(['""]Content-Security-Policy helmet\(\) ``` **없으면 경고** #### C. HTTPS 강제 여부 **검색:** ```regex (app\.use\(|middleware.*)(https|ssl|secure) ``` **Production에서 HTTPS 강제하는지 확인** ### 5. 인증/인가 보안 #### A. JWT 검증 **위험한 패턴:** ```regex jwt\.decode\( ``` **안전한 패턴:** ```regex jwt\.verify\( ``` **decode만 사용하고 verify 안 하면 경고** **예시:** ```javascript // 위험 const decoded = jwt.decode(token) // 검증 없음! // 안전 const decoded = jwt.verify(token, SECRET_KEY) ``` #### B. 비밀번호 해싱 **검색:** - bcrypt, argon2, scrypt 사용 여부 - 평문 비밀번호 저장 여부 **위험한 패턴:** ```regex password\s*[:=]\s*req\.(body|params|query)\.password INSERT.*password.*VALUES.*\$\{ ``` **안전한 패턴:** ```regex bcrypt\.(hash|compare) argon2\.(hash|verify) ``` #### C. 세션 보안 **검색:** - `express-session` 설정 - `httpOnly`, `secure`, `sameSite` 쿠키 옵션 ```javascript // 안전한 설정 session({ cookie: { httpOnly: true, secure: true, // HTTPS only sameSite: 'strict' } }) ``` ### 6. 프론트엔드 보안 (React/Vue/등) #### A. 외부 스크립트 로딩 **위험한 패턴:** ```regex ` 삽입 **수정 방법**: ```javascript // 방법 1: textContent 사용 profileDiv.textContent = userData.bio; // 방법 2: sanitize 라이브러리 import DOMPurify from 'dompurify'; profileDiv.innerHTML = DOMPurify.sanitize(userData.bio); ``` #### 위치 2: [src/pages/Comments.tsx:45](src/pages/Comments.tsx#L45) **위험한 코드**: ```tsx ``` **수정 방법**: ```tsx // sanitize 후 사용 // 또는 일반 텍스트로