.claude/skills/verify-security/SKILL.md
보안 설정을 검증합니다. Helmet CSP, Next.js Security Headers, PermissionsGuard 모드, @Public 남용 검사.
npx skillsauth add junnv93/equipment_management_system verify-securityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
프로덕션 보안 설정이 올바르게 구성되어 있는지 검증합니다:
| File | Purpose |
|------|---------|
| apps/backend/src/common/middleware/helmet-config.ts | Helmet CSP 설정 |
| apps/frontend/next.config.js | Next.js Security Headers |
| apps/backend/src/modules/auth/guards/permissions.guard.ts | PermissionsGuard |
| apps/backend/src/modules/auth/decorators/public.decorator.ts | @Public() 데코레이터 |
| apps/backend/src/common/guards/internal-api-key.guard.ts | InternalApiKey Guard |
| apps/backend/src/common/guards/internal-api-throttler.guard.ts | InternalApiThrottlerGuard |
| apps/frontend/lib/api/server-api-client.ts | Server Component API 클라이언트 |
| apps/backend/src/common/decorators/site-scoped.decorator.ts | @SiteScoped() 데코레이터 |
| apps/backend/src/common/interceptors/site-scope.interceptor.ts | SiteScopeInterceptor |
| apps/backend/src/common/utils/enforce-site-access.ts | 크로스 사이트/팀 접근 제어 |
각 Step의 bash 명령어, 코드 예시: references/step-details.md 참조
PASS: scriptSrc 환경별 분리, 프로덕션 ["'self'"]만. FAIL: 구분 없이 unsafe-* 포함.
PASS: 6개 필수 헤더 모두 설정. FAIL: headers() 없거나 헤더 누락.
PASS: PERMISSIONS_GUARD_MODE 환경변수 참조 + .env.example 문서화.
PASS: @Public() + @Post/@Patch/@Delete 조합 0개 (test-login 제외).
PASS: critical 0개 + 프로덕션 high pnpm.overrides로 미티게이션.
PASS: @SiteScoped() + @UseInterceptors(SiteScopeInterceptor) 쌍. Implicit 패턴 0개.
PASS: HTTP 메서드 수 ≈ 보안 데코레이터 수. 각 엔드포인트에 @RequirePermissions/@SkipPermissions/@Public 중 하나.
PASS: InternalApiThrottlerGuard가 APP_GUARD로 등록. shouldSkip()이 X-Internal-Api-Key 검증.
PASS: server-api-client.ts에 헤더 전송 코드 + .env.local에 INTERNAL_API_KEY 존재.
PASS: 4-param 시그니처, ErrorCode.ScopeAccessDenied SSOT, scope.type === 'none' fail-close, team→site defense-in-depth.
| # | 검사 | 상태 | 상세 |
| --- | --------------------------- | --------- | ------------------------------------------ |
| 1 | Helmet CSP 프로덕션 | PASS/FAIL | scriptSrc 환경별 분리 여부 |
| 2 | Next.js Security Headers | PASS/FAIL | 누락된 헤더 목록 |
| 3 | PermissionsGuard 모드 | PASS/FAIL | DENY 모드 설정 가능 여부 |
| 4 | @Public() 남용 | PASS/FAIL | 상태 변경 엔드포인트 목록 |
| 5 | pnpm audit + overrides | PASS/FAIL | critical 0 + 프로덕션 high 미티게이션 |
| 6 | @SiteScoped 데이터 격리 | PASS/FAIL | 누락 컨트롤러, bypassRoles 설정 |
| 7 | 엔드포인트 보안 데코레이터 | PASS/FAIL | 미어노테이션 엔드포인트 수 |
| 8 | Throttle Guard 등록 | PASS/FAIL | InternalApiThrottlerGuard 사용 여부 |
| 9 | SSR X-Internal-Api-Key | PASS/FAIL | 헤더 전송 코드 존재 여부 |
| 10 | enforceSiteAccess 팀 격리 | PASS/FAIL | entityTeamId 전달 여부 |
@Public() + @Post 허용 (인증 전/갱신)@Public() + GET 정상POST /users/sync — @Public() + @UseGuards(InternalApiKeyGuard) + @Post 정상@Public() + @Get() 정상 (인프라 컨트롤러)@Public() + @SkipPermissions() — 테스트 전용 엔드포인트POST/DELETE me/signature — @SkipPermissions() 사용하나 req.user.userId로 본인만 변경, MIME 타입(PNG/JPEG) + 2MB 크기 제한 적용GET /api/files/:subdir/:filename — @SkipPermissions() 사용하나 전역 JwtAuthGuard로 인증 보장 (미인증 401). 특정 권한 불필요, 인증된 사용자 전체 허용이 의도적 설계. Path traversal 방지(safeSubdir/safeFilename) 적용.testing
Verifies Zod validation pattern compliance — ZodValidationPipe usage (no class-validator), versionedSchema inclusion in state-change DTOs, controller pipe application, query DTO consistency. Run after adding/modifying DTOs or controller endpoints.
testing
Verifies cross-feature workflow E2E test coverage against critical-workflows.md checklist. Checks WF-01~WF-35 coverage, step completeness, role correctness, side-effect verification, and status transition assertions. Run after adding workflow tests or before PR.
testing
SSOT(Single Source of Truth) 임포트 소스를 검증합니다. 타입/enum/상수가 올바른 패키지에서 임포트되는지 확인. 타입/enum 추가/수정 후 사용.
development
Verifies SQL safety — LIKE wildcard escaping, N+1 query pattern detection, COUNT(DISTINCT) for fan-out JOINs, RBAC INNER JOIN enforcement. Run after adding/modifying search or list API endpoints.