긴급 보안 개선 TODO는
docs/SECURITY_REMEDIATION_TODO.md를 기준으로 관리한다. 운영 서비스에서는 IDOR/결제 웹훅/사용자 업로드 파일 접근 통제를 UI 개선보다 우선한다.
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
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에서 개별 오버라이드한다.
- 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)
- 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 Requestswhen limits are exceeded. - Redis 장애 시: fail-closed — rate limit 검사 자체가 실패하면 통과시키지
않고
RATE_LIMITED로 막는다(가용성보다 이메일 폭탄 방지 우선).
{
"status": "RATE_LIMITED",
"reason": "email_cooldown|ip_cooldown|daily_limit_exceeded",
"retry_after": 300
}이메일 인증 재전송(/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)
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
- 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
Sensitive actions are recorded in the system audit logs for security monitoring.
- Client IP Address
- User-Agent
- Request Timestamp
- User ID
- Action Context
{
"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"
}
}-
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.
docs/SECURITY_REMEDIATION_TODO.mdbackend/core/security.pybackend/core/dependencies.pybackend/core/config.pybackend/CRUD/email_token/email_token_service.pyfrontend/src/pages/login/ResetPasswordPage.tsx