보안 감사 결과 CRITICAL 2건, HIGH 5건 발견 → 수정 완료 + 자동화 구축. [보안 수정] - issue-view.js: 하드코딩 비밀번호 → crypto.getRandomValues() 랜덤 생성 - pushSubscriptionController.js: ntfy 비밀번호 → process.env.NTFY_SUB_PASSWORD - DEPLOY-GUIDE.md/PROGRESS.md/migration SQL: 평문 비밀번호 → placeholder - docker-compose.yml/.env.example: NTFY_SUB_PASSWORD 환경변수 추가 [보안 강제 시스템 - 신규] - scripts/security-scan.sh: 8개 규칙 (CRITICAL 2, HIGH 4, MEDIUM 2) 3모드(staged/all/diff), severity, .securityignore, MEDIUM 임계값 - .githooks/pre-commit: 로컬 빠른 피드백 - .githooks/pre-receive-server.sh: Gitea 서버 최종 차단 bypass 거버넌스([SECURITY-BYPASS: 사유] + 사용자 제한 + 로그) - SECURITY-CHECKLIST.md: 10개 카테고리 자동/수동 구분 - docs/SECURITY-GUIDE.md: 운영자 가이드 (워크플로우, bypass, FAQ) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.4 KiB
4.4 KiB
보안 시스템 운영 가이드
개요
TK Factory Services에는 2계층 보안 검사 시스템이 적용되어 있습니다.
| 계층 | 위치 | 역할 | 우회 가능 |
|---|---|---|---|
| pre-commit | 로컬 (개발자 PC) | 빠른 피드백 | --no-verify |
| pre-receive | Gitea 서버 | 최종 차단 | [SECURITY-BYPASS: 사유]만 |
개발 워크플로우
코드 작성 → git add → git commit
↓
pre-commit hook
(security-scan.sh --staged)
↓
위반 있으면 → 커밋 차단 + 상세 출력
위반 없으면 → 커밋 성공
↓
git push
↓
pre-receive hook (서버)
(diff 기반 검사)
↓
위반 있으면 → push 차단
위반 없으면 → push 성공
위반 발생 시 대처
에러 메시지 읽기
[SECURITY] 2 issue(s) found:
✗ [CRITICAL] #1 SECRET_HARDCODE — 비밀정보 하드코딩
→ src/controllers/auth.js:64
password: 'my-secret-123'
[CRITICAL]/[HIGH]→ 차단됨, 반드시 수정[MEDIUM]→ 경고, 5개 초과 시 차단→ 파일:라인번호→ 수정할 위치- 아래 줄 → 문제가 된 코드
수정 방법 (규칙별)
| 규칙 | 수정 방법 |
|---|---|
| SECRET_HARDCODE | process.env.변수명으로 이동, .env에 추가 |
| LOCALSTORAGE_AUTH | HttpOnly 쿠키 또는 Authorization 헤더 사용 |
| INNERHTML_XSS | textContent 사용 또는 DOMPurify 적용 |
| CORS_WILDCARD | 허용 도메인을 명시적으로 나열 |
| SQL_INTERPOLATION | 파라미터화 쿼리(? placeholder) 사용 |
| LOG_SECRET | 로그에서 비밀정보 제거 |
bypass 사용법 (긴급 시)
형식
git commit -m "fix: 긴급 장애 대응 [SECURITY-BYPASS: prod 서비스 다운 긴급 핫픽스]"
규칙
- 사유 필수:
[SECURITY-BYPASS]만으로는 거부됨 - 허용 사용자만: 운영담당자(ahn@hyungi.net)만 bypass 가능
- 24시간 내 수정: bypass 후 반드시 보안 이슈 수정 PR 제출
- 로그 기록: 모든 bypass는 서버에 자동 기록됨
bypass 후 조치
- bypass한 코드의 보안 이슈 파악
- 24시간 내 수정 커밋
security-scan.sh --all로 전체 검증
규칙 추가/수정 방법
새 규칙 추가
scripts/security-scan.sh의 RULES 배열에 추가:
'RULE_NAME|SEVERITY|설명|REGEX_PATTERN'
예시:
'EVAL_USAGE|HIGH|eval 사용 위험|eval\s*\('
같은 규칙을 서버에도 반영
.githooks/pre-receive-server.sh의 RULES 배열에도 동일하게 추가.
Gitea 서버의 hook 파일도 업데이트 필요.
false positive 등록
파일 단위 제외
.securityignore에 추가 (주석 필수):
path/to/file.js # 사유 설명 (날짜)
라인 단위 제외
소스 코드에 인라인 주석:
const pattern = /password/; // security-ignore: SECRET_HARDCODE — regex 패턴 정의
주의
- 주석 없는 항목은 스캔 시 경고
- 월 1회
.securityignore검토하여 불필요 항목 제거
수동 검사
전체 프로젝트 스캔
./scripts/security-scan.sh --all
엄격 모드 (MEDIUM도 차단)
./scripts/security-scan.sh --all --strict
두 커밋 간 비교
./scripts/security-scan.sh --diff HEAD~5 HEAD
초기 설정 (새 머신)
# 1. git hooks 경로 설정
git config core.hooksPath .githooks
# 2. 전체 스캔 확인
./scripts/security-scan.sh --all
# 3. 테스트 (선택)
echo "password: 'test'" >> /tmp/test.js
git add /tmp/test.js
git commit -m "test" # → 차단되어야 함
FAQ
Q: pre-commit이 너무 느리다
A: staged 파일만 검사하므로 보통 1초 이내. 파일이 많으면 --no-verify로 우회 후 push 시 서버에서 검사.
Q: false positive가 계속 뜬다
A: .securityignore에 등록하거나 라인에 // security-ignore: RULE_NAME 추가.
Q: 규칙을 비활성화하고 싶다 A: RULES 배열에서 해당 규칙을 주석 처리. 단, CRITICAL 규칙 비활성화는 비권장.
Q: 새 서비스 추가 시
A: 추가 설정 불필요. .securityignore에 제외할 파일이 있으면 등록.