From d69be34bb1417462b56314ec80a3af2d900c96ec Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 17 Jul 2026 21:51:26 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?Fix=20DoS=20vulnerability=20via=20TypeError=20in=20hmac.compare?= =?UTF-8?q?=5Fdigest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What (구현 내용): `hmac.compare_digest()`에 전달되는 `provided` 및 `expected` 문자열을 바이트 객체(UTF-8)로 인코딩하도록 수정했습니다. Why (해결하는 문제): 파이썬의 `hmac.compare_digest()`는 인자가 문자열일 경우, 오직 ASCII 문자만 허용합니다. 만약 공격자가 Authorization 헤더에 Non-ASCII 문자(예: `Bearer 漢字`)를 주입하면, 내부적으로 `TypeError`가 발생하여 어플리케이션이 500 Internal Server Error로 응답합니다. 이를 악용한 DoS 공격이나 에러 로그 범람 위험이 존재했습니다. Impact (성능/영향): 바이트 객체로 비교함으로써, 어떠한 문자열 입력에 대해서도 안전하게 상수 시간 비교(constant-time comparison)를 수행하며 `TypeError`에 의한 에러를 사전에 방지합니다. Measurement (측정/검증 방법): 기존 인증 관련 테스트 코드가 모두 100% 분기 커버리지(branch coverage)와 함께 통과함을 `pytest`를 통해 검증했습니다. --- .jules/sentinel.md | 5 +++++ src/newsdom_api/main.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 2b5d819c..aabf99a6 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -90,3 +90,8 @@ **Vulnerability:** The `_safe_upload_filename` function used `filename.replace`, `PurePosixPath`, and `re.sub` on unbounded client input, making it vulnerable to ReDoS or CPU/memory exhaustion (DoS) when fed extremely long strings. **Learning:** Even fast standard library functions like `PurePosixPath` and string replacements can cause significant lag when chained on strings in the megabytes. String processing operations should always bound their inputs first if the input is untrusted and can be arbitrarily large. **Prevention:** Cap the length of client-provided filename strings early by slicing them (e.g. `filename = filename[-512:]`) before doing more complex string parsing or regex replacements, especially when only the basename suffix is relevant. + +## 2025-07-17 - Prevent DoS via TypeError in hmac.compare_digest +**Vulnerability:** Passing strings containing non-ASCII characters directly to `hmac.compare_digest()` raises a `TypeError`, causing a 500 Internal Server Error. This can be exploited by an attacker sending malformed Authorization headers (e.g., `Bearer 漢字`) to cause a Denial of Service (DoS) on protected endpoints. +**Learning:** `hmac.compare_digest()` in Python does not support comparing strings with non-ASCII characters; it strictly requires ASCII strings or bytes-like objects. +**Prevention:** Always encode strings to bytes (e.g., `.encode("utf-8")`) before passing them to `hmac.compare_digest()` when handling untrusted client input. diff --git a/src/newsdom_api/main.py b/src/newsdom_api/main.py index 4efdad56..ca5b7599 100644 --- a/src/newsdom_api/main.py +++ b/src/newsdom_api/main.py @@ -133,7 +133,7 @@ def require_authorization( return expected = f"Bearer {token}" provided = authorization or "" - if not hmac.compare_digest(provided, expected): + if not hmac.compare_digest(provided.encode("utf-8"), expected.encode("utf-8")): raise HTTPException( status_code=401, detail=UNAUTHORIZED_DETAIL,