--- 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 > .gitignore echo ".env.local" >> .gitignore git add .gitignore git commit -m "Add .env to gitignore" ``` **추가 확인**: Git 히스토리에 이미 커밋되었는지 확인 ```bash git log --all --full-history -- .env ``` --- ### 2. 하드코딩된 API 키 발견 ❌ **파일**: [src/config/api.js:15](src/config/api.js#L15) **발견 내용**: ```javascript const API_KEY = "your_actual_api_key_here_redacted"; ``` **위험도**: 매우 높음 **영향**: API 키가 소스 코드에 노출되어 누구나 확인 가능 **즉시 조치:** 1. `.env` 파일로 이동: ```bash # .env API_KEY=your_actual_api_key_here ``` 2. 코드 수정: ```javascript const API_KEY = process.env.API_KEY; ``` 3. **중요**: 노출된 키는 즉시 폐기하고 새로 발급 - Stripe 대시보드에서 해당 키 삭제 - 새 키 발급 후 `.env`에만 저장 --- ### 3. Git 히스토리에 .env 파일 커밋 발견 ❌ **커밋**: [a1b2c3d](commit/a1b2c3d) (2024-10-15) **파일**: `.env` **위험도**: 매우 높음 **영향**: GitHub에 이미 푸시되었다면 환경 변수가 공개 이력에 남음 **즉시 조치:** ```bash # 1. BFG Repo-Cleaner 설치 (권장) brew install bfg # macOS # 또는 https://rtyley.github.io/bfg-repo-cleaner/ # 2. .env 파일을 히스토리에서 완전 제거 bfg --delete-files .env # 3. 히스토리 정리 git reflog expire --expire=now --all git gc --prune=now --aggressive # 4. Force push (주의: 팀원과 조율 필요) git push origin --force --all ``` **주의**: Force push는 팀 전체에 영향을 미치므로 반드시 팀원들과 조율 **노출된 모든 시크릿 교체 필요** --- ## ⚠️ 경고 (빠른 수정 권장) ### 1. npm audit에서 5개의 취약점 발견 **세부 내용**: #### Critical (1개) - **lodash** 4.17.15 - 취약점: Prototype Pollution - CVSS: 9.8 - 수정 버전: 4.17.21 - 조치: `npm install lodash@latest` #### High (2개) - **axios** 0.21.0 - 취약점: SSRF (Server-Side Request Forgery) - CVSS: 8.1 - 수정 버전: 0.21.4 - **minimist** 1.2.5 - 취약점: Prototype Pollution - 수정 버전: 1.2.8 #### Moderate (2개) - **url-parse** 1.5.3 - **ws** 7.4.5 **즉시 조치:** ```bash npm audit fix # 또는 수동으로 npm install lodash@latest axios@latest minimist@latest ``` --- ### 2. SQL Injection 위험 코드 발견 (3곳) #### 위치 1: [src/db/users.js:42](src/db/users.js#L42) **위험한 코드**: ```javascript const query = "SELECT * FROM users WHERE id = " + req.params.id; db.query(query); ``` **위험도**: 높음 **공격 시나리오**: `id=1 OR 1=1; DROP TABLE users;--` **수정 방법**: ```javascript // Parameterized Query 사용 const query = "SELECT * FROM users WHERE id = ?"; db.query(query, [req.params.id]); // 또는 ORM 사용 (Sequelize, TypeORM 등) const user = await User.findByPk(req.params.id); ``` #### 위치 2: [src/api/products.js:58](src/api/products.js#L58) **위험한 코드**: ```javascript db.query(`DELETE FROM products WHERE category = '${category}'`); ``` **수정 방법**: ```javascript db.query("DELETE FROM products WHERE category = ?", [category]); ``` #### 위치 3: [src/services/search.js:23](src/services/search.js#L23) **위험한 코드**: ```javascript const sql = `SELECT * FROM items WHERE name LIKE '%${searchTerm}%'`; ``` **수정 방법**: ```javascript const sql = "SELECT * FROM items WHERE name LIKE ?"; db.query(sql, [`%${searchTerm}%`]); ``` --- ### 3. XSS 취약점 발견 (2곳) #### 위치 1: [src/components/Profile.jsx:28](src/components/Profile.jsx#L28) **위험한 코드**: ```javascript profileDiv.innerHTML = userData.bio; ``` **위험도**: 중간-높음 **공격 시나리오**: bio에 `` 삽입 **수정 방법**: ```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 후 사용
// 또는 일반 텍스트로
{comment.text}
``` --- ### 4. CORS 설정이 너무 관대함 **파일**: [server.js:10](server.js#L10) **현재 설정**: ```javascript app.use(cors({ origin: '*' })); ``` **위험도**: 중간 **영향**: 모든 도메인에서 API 접근 가능 (CSRF 공격 위험) **수정 방법**: ```javascript // 특정 도메인만 허용 app.use(cors({ origin: [ 'https://yourdomain.com', 'https://app.yourdomain.com' ], credentials: true })); // 또는 환경 변수로 app.use(cors({ origin: process.env.ALLOWED_ORIGINS.split(','), credentials: true })); ``` --- ### 5. 보안 헤더 미설정 **발견 내용**: Express 서버에 보안 헤더가 설정되지 않음 **누락된 헤더**: - X-Frame-Options (Clickjacking 방지) - Content-Security-Policy (XSS 방지) - X-Content-Type-Options (MIME 스니핑 방지) - Strict-Transport-Security (HTTPS 강제) **수정 방법**: ```bash npm install helmet ``` ```javascript // server.js const helmet = require('helmet'); app.use(helmet()); // 또는 세밀한 설정 app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'"], imgSrc: ["'self'", "data:", "https:"] } }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true } })); ``` --- ## 💡 주의 (개선 권장) ### 1. JWT 검증 누락 가능성 **파일**: [src/middleware/auth.js:18](src/middleware/auth.js#L18) **발견 내용**: ```javascript const decoded = jwt.decode(token); ``` **권장**: `verify` 사용 ```javascript const decoded = jwt.verify(token, process.env.JWT_SECRET); ``` --- ### 2. 오래된 패키지 다음 패키지들의 Major 버전이 크게 뒤쳐져 있습니다: | 패키지 | 현재 | 최신 | 업데이트 | |--------|------|------|----------| | react | 16.14.0 | 18.2.0 | Major | | express | 4.17.1 | 4.18.2 | Minor | | webpack | 4.46.0 | 5.88.2 | Major | **조치**: 점진적 업데이트 권장 (Breaking changes 확인 필요) --- ### 3. localStorage에 토큰 저장 **파일**: [src/utils/auth.js:12](src/utils/auth.js#L12) ```javascript localStorage.setItem('authToken', token); ``` **권장**: httpOnly 쿠키 사용 (XSS로부터 보호) --- ## ✅ 양호 ### .gitignore 설정 ✅ `node_modules/` 포함됨 ✅ `*.log` 포함됨 ✅ `.DS_Store` 포함됨 ### 비밀번호 해싱 ✅ bcrypt 사용 확인 ([src/auth/password.js:25](src/auth/password.js#L25)) ### HTTPS 사용 ✅ Production에서 HTTPS 강제 ([server.js:45](server.js#L45)) --- ## 📈 상세 점수 | 카테고리 | 점수 | 상태 | |---------|------|------| | 민감 정보 관리 | 25/40 | 🚨 심각 | | 의존성 보안 | 15/20 | ⚠️ 경고 | | 코드 보안 | 18/30 | ⚠️ 경고 | | 설정 보안 | 10/20 | 💡 주의 | | 인증/인가 | 8/10 | ✅ 양호 | **전체 점수: 76/120 → 63/100** --- ## 🎯 즉시 조치 항목 (우선순위) ### 오늘 반드시 수정: 1. ❌ `.env`를 `.gitignore`에 추가 2. ❌ `src/config/api.js`의 하드코딩된 API 키 제거 3. ❌ 노출된 API 키 폐기 및 재발급 ### 이번 주 내 수정: 4. ⚠️ Git 히스토리에서 `.env` 제거 5. ⚠️ SQL Injection 코드 수정 (3곳) 6. ⚠️ npm audit fix 실행 7. ⚠️ XSS 취약점 수정 (2곳) ### 이번 달 내 개선: 8. 💡 helmet.js 설치 및 설정 9. 💡 CORS 설정 강화 10. 💡 주요 패키지 업데이트 --- ## 📚 보안 개선 권장 사항 ### 단기 (1주) - [ ] 모든 심각/경고 항목 수정 - [ ] pre-commit hook 설정 (시크릿 검사) - [ ] 팀 보안 가이드라인 작성 ### 중기 (1개월) - [ ] 정기적 보안 스캔 CI/CD 통합 - [ ] 의존성 자동 업데이트 (Dependabot) - [ ] 보안 교육 실시 ### 장기 (분기) - [ ] 침투 테스트 수행 - [ ] 보안 감사 (Security Audit) - [ ] Bug Bounty 프로그램 고려 --- ## 🔧 자동 수정 가능 항목 다음 항목은 자동으로 수정할 수 있습니다. 진행할까요? 1. `.gitignore`에 `.env` 추가 2. `npm audit fix` 실행 3. `helmet` 설치 및 기본 설정 4. 오래된 패키지 업데이트 (Minor 버전만) --- ## 🔐 보안 체크리스트 다음 보안 검사를 통과했습니다: - [ ] 환경 변수 관리 - [ ] .env가 .gitignore에 있음 - [ ] Git 히스토리에 시크릿 없음 - [ ] 하드코딩된 키 없음 - [ ] 의존성 보안 - [ ] 알려진 취약점 없음 - [ ] 최신 버전 사용 - [ ] 코드 보안 - [ ] SQL Injection 방지 - [ ] XSS 방지 - [ ] CSRF 방지 - [ ] 서버 설정 - [ ] 보안 헤더 설정 - [ ] HTTPS 사용 - [ ] CORS 적절히 설정 **전체 체크리스트: 8/16 완료 (50%)** --- ## ⏭️ 다음 단계 1. **즉시**: 심각 항목 3개 수정 2. **오늘 중**: npm audit fix 실행 3. **내일**: SQL Injection 및 XSS 코드 수정 4. **이번 주**: 보안 헤더 설정 및 CORS 강화 5. **정기적**: 매주 보안 스캔 실행 (`/security-check`) --- 보안은 지속적인 프로세스입니다. 정기적으로 점검하세요! 🔒 ``` --- ### 9. 자동 수정 제안 (선택적) 사용자에게 물어본 후, 안전하게 자동 수정 가능한 항목 처리: #### A. .gitignore 업데이트 ```bash cat >> .gitignore << EOF # Environment variables .env .env.local .env.*.local # Secrets *.key *.pem credentials.json secrets.json EOF ``` #### B. npm audit fix ```bash npm audit fix ``` #### C. helmet 설치 ```bash npm install helmet ``` **사용자에게 확인 후 실행** ### 10. CI/CD 통합 제안 **.github/workflows/security-check.yml** 생성 제안: ```yaml name: Security Check on: [push, pull_request] jobs: security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Run npm audit run: npm audit - name: Check for secrets uses: trufflesecurity/trufflehog@main ``` ## Important Notes: ### 우선순위 1. **민감 정보 노출** - 가장 높음 2. **의존성 취약점** - 높음 3. **코드 취약점** - 중간-높음 4. **설정 문제** - 중간 ### False Positive 최소화 - 테스트 파일은 우선순위 낮춤 - 주석은 별도 표시 - `example`, `placeholder` 같은 명확한 예시는 제외 ### 사용자 경험 - 한국어로 명확하게 설명 - 각 문제에 대한 **구체적인 수정 방법** 제시 - 위험도와 영향을 명확히 설명 - 즉시 조치 항목과 장기 개선 항목 구분 ### 에러 처리 - Git이 없는 프로젝트도 처리 - package.json이 없으면 해당 섹션 스킵 - 권한 문제 등 예외 상황 안내 ### 보안 - 리포트에 실제 시크릿 전문을 노출하지 말 것 (마스킹) - 민감한 정보는 일부만 표시 (예: `api_key_abc...xyz`)