Skip to content

Security: Seongwonp/CSAT_Forge

Security

docs/SECURITY.md

Security & Rate Limit Policies

긴급 보안 개선 TODO는 docs/SECURITY_REMEDIATION_TODO.md를 기준으로 관리한다. 운영 서비스에서는 IDOR/결제 웹훅/사용자 업로드 파일 접근 통제를 UI 개선보다 우선한다.

0. Security Logic Flow: Password Reset

sequenceDiagram
    participant U as User (IP Tracking)
    participant B as Backend (Rate Limit)
    participant R as Redis
    participant E as Email Service

    U->>B: Request Password Reset
    B->>R: Check Email/IP Cooldown & Daily Limit
    R-->>B: Limit Ok
    B->>R: Store Token (TTL 1h)
    B->>E: Send Secure Link
    U->>B: Reset Password with Token
    B->>R: Validate & Delete Token
    B-->>U: Success & Audit Log Recorded
Loading

1. Rate Limit Settings

Overview

Policies to prevent automated attacks and repetitive requests, primarily focused on sensitive operations like password resets.

⚠️ 2026-07-29 정정: 이전엔 이 표가 dev/prod 값을 분리 기재했으나, 실제 코드는 EmailTokenService에 dev용 단축값(30초/60초/일 50회)이 환경 분기 없이 하드코딩돼 있어 운영에도 그대로 나가고 있었다(코덱스 리뷰로 발견). 이제 값은 Settings(backend/core/config.py)로 옮겼고, 코드 기본값 자체가 운영 기준이다. 로컬 개발 시 낮추고 싶으면 .env에서 개별 오버라이드한다.

Rate Limit Values (code default = production)

  • Email Cooldown: 5 minutes (PASSWORD_RESET_EMAIL_COOLDOWN_SECONDS)
  • IP Cooldown: 10 minutes (PASSWORD_RESET_IP_COOLDOWN_SECONDS)
  • Daily Max Requests: 5 (PASSWORD_RESET_MAX_DAILY)

Implementation Details

  • Storage: Redis. Email/IP cooldown은 SET key value NX EX로 검사와 점유를 한 번의 원자적 연산으로 수행한다(이전엔 TTL 조회 후 별도 setex라 동시 요청이 둘 다 통과하는 레이스가 있었음). 일일 카운트는 INCR(최초 증가 시에만 자정까지 EXPIRE)로 lost-update 없이 누적한다.
  • Location: backend/CRUD/email_token/email_token_service.py (_try_claim_password_reset_slot)
  • Response: Returns 429 Too Many Requests when limits are exceeded.
  • Redis 장애 시: fail-closed — rate limit 검사 자체가 실패하면 통과시키지 않고 RATE_LIMITED로 막는다(가용성보다 이메일 폭탄 방지 우선).
{
  "status": "RATE_LIMITED",
  "reason": "email_cooldown|ip_cooldown|daily_limit_exceeded",
  "retry_after": 300
}

1-1. Email Verification Resend

이메일 인증 재전송(/resend-token)도 같은 원자화 패턴을 쓴다(2026-07-29, 코덱스 리뷰로 동일한 check-then-set 레이스 + fail-open 발견 후 수정).

  • Cooldown: 60초 (EMAIL_RESEND_COOLDOWN_SECONDS, backend/core/config.py)
  • Storage: SET key value NX EX로 원자적 점유. Redis 장애 시 fail-closed.
  • Location: backend/CRUD/email_token/email_token_service.py (_try_claim_resend_slot)

2. Password Policies

Complexity Requirements

To ensure account security, passwords must meet the following criteria:

  • Minimum 10 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • At least one special character

Implementation

  • Backend: backend/core/security.py
  • Backend schema validators: backend/schemas/user_schema.py
  • Frontend: frontend/src/pages/login/ResetPasswordPage.tsx, frontend/src/pages/signup/SignupPage.tsx, frontend/src/pages/settings/SettingsPage.tsx

3. Audit Logging

Sensitive actions are recorded in the system audit logs for security monitoring.

Logged Information

  • Client IP Address
  • User-Agent
  • Request Timestamp
  • User ID
  • Action Context

Audit Log Example (Action: PASSWORD_RESET)

{
  "action_type": "PASSWORD_RESET",
  "target_type": "USER",
  "target_id": 123,
  "ip_address": "192.168.1.1",
  "reason": "Password reset via email token",
  "target_extra": {
    "client_ip": "192.168.1.1",
    "user_agent": "Mozilla/5.0...",
    "source": "password_reset",
    "trigger": "user_initiated"
  }
}

4. Operation Checklist

  • docs/SECURITY_REMEDIATION_TODO.md의 P0 항목 완료 여부 확인.
  • 사용자 소유 리소스 조회 API가 모두 user_id 소유권 검사를 수행하는지 확인.
  • Toss 웹훅은 운영 환경에서 서명 검증 없이는 수신하지 않도록 확인.
  • /static/uploads 공개 접근이 사용자 콘텐츠 유출로 이어지지 않도록 인증 기반 서빙으로 전환.
  • 프록시 환경에서 X-Forwarded-For 신뢰 범위가 제한되어 있는지 확인.
  • 비밀번호 변경/재설정 시 refresh token + single-session 상태를 함께 폐기하는지 확인.
  • 비밀번호 최소 길이/복잡도 정책을 backend schema와 frontend UI에서 동일하게 적용하는지 확인.
  • Verify Redis connectivity for rate limiting.
  • Confirm environment-specific rate limit values in backend/.env.
  • Ensure audit logs are correctly capturing client IP and User-Agent.
  • Review user-facing error messages for clarity and security.

5. Related Files

  • docs/SECURITY_REMEDIATION_TODO.md
  • backend/core/security.py
  • backend/core/dependencies.py
  • backend/core/config.py
  • backend/CRUD/email_token/email_token_service.py
  • frontend/src/pages/login/ResetPasswordPage.tsx

There aren't any published security advisories