Files
gh-lightsoft-dev-claude-plu…/commands/security-check.md
2025-11-30 08:37:48 +08:00

1025 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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
<div dangerouslySetInnerHTML={{ __html: userData }} />
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
<script\s+src=['""]http://
eval\(
```
**CDN은 HTTPS 사용 권장**
#### B. localStorage에 민감 정보
**검색:**
```regex
localStorage\.setItem\([^)]*token
localStorage\.setItem\([^)]*password
sessionStorage\.setItem\([^)]*token
```
**권장: httpOnly 쿠키 또는 메모리에만 저장**
### 7. Docker/컨테이너 보안 (선택적)
**Dockerfile이 있으면:**
#### A. Root 사용자 회피
```dockerfile
# 위험
RUN apt-get install
# 안전
USER node
RUN apt-get install
```
#### B. 시크릿을 이미지에 복사하지 않음
```dockerfile
# 위험
COPY .env /app/.env
# 안전: 환경 변수로 주입
```
### 8. 상세 보안 리포트 생성
모든 검사를 완료한 후, 다음 형식으로 종합 리포트를 생성하세요:
---
```markdown
# 🔒 보안 검사 리포트
생성 일시: 2024-11-14 15:30:00
프로젝트: [프로젝트명]
---
## 📊 전체 요약
| 심각도 | 개수 |
|--------|------|
| 🚨 심각 (Critical) | 3 |
| ⚠️ 경고 (High) | 5 |
| 💡 주의 (Medium) | 8 |
| 정보 (Low) | 2 |
**전체 보안 점수: 68/100** (개선 필요)
---
## 🚨 심각 (즉시 수정 필요)
### 1. .env 파일이 .gitignore에 없음 ❌
**위치**: 루트 디렉토리
**발견 내용**: `.env` 파일이 존재하지만 `.gitignore`에 포함되지 않음
**위험도**: 매우 높음
**영향**: 환경 변수가 Git에 커밋되어 GitHub에 노출될 위험
**즉시 조치:**
```bash
echo ".env" >> .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에 `<script>alert('XSS')</script>` 삽입
**수정 방법**:
```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
<div dangerouslySetInnerHTML={{ __html: comment.text }} />
```
**수정 방법**:
```tsx
// sanitize 후 사용
<div dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(comment.text)
}} />
// 또는 일반 텍스트로
<div>{comment.text}</div>
```
---
### 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`)