From d48d8af7b67d40b93af3815aa02018333ac2eebf Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:12:43 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?hmac.compare=5Fdigest=20=EC=9E=85=EB=A0=A5=EA=B0=92=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20500=20=EC=97=90=EB=9F=AC=20=EC=B7=A8?= =?UTF-8?q?=EC=95=BD=EC=A0=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `hmac.compare_digest` 함수가 non-ASCII 문자열을 처리할 때 발생하는 TypeError(500 에러) 취약점을 수정했습니다. 두 문자열을 명시적으로 utf-8로 인코딩한 뒤 비교하도록 변경했습니다. --- .jules/sentinel.md | 4 ++++ CHANGELOG.md | 1 + saas_web.py | 3 ++- tests/test_saas_web.py | 12 ++++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 9c9d083b..626011bd 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -1,3 +1,7 @@ +## 2024-05-15 - Prevent 500 errors with HMAC non-ASCII inputs +**Vulnerability:** Unhandled TypeError (and 500 Server Error) when `hmac.compare_digest` processes non-ASCII strings. +**Learning:** Python`s `hmac.compare_digest` does not support comparing strings with non-ASCII characters directly. +**Prevention:** Always encode both strings to `utf-8` bytes before comparison to prevent unhandled TypeError exceptions. ## 2026-07-25 - [Cross-platform upload basename normalization] **Behavior:** Upload metadata now interprets both forward slashes and backslashes as path separators before extracting a basename. **Learning:** On POSIX systems, `pathlib.Path(filename).name` retains backslashes because they are ordinary characters there. That caused inconsistent manifest and converter filenames for Windows-style client paths. The upload itself is still written inside a trusted temporary workspace, and batch archive entry names are generated outputs; this change does not establish a filesystem traversal or archive-entry escape. diff --git a/CHANGELOG.md b/CHANGELOG.md index 9313538b..90457a54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [Unreleased] +- **보안(Security)**: `hmac.compare_digest` 함수에 non-ASCII 문자가 입력될 경우 발생하는 500 에러를 수정했습니다. ### Added - 다중 파일 업로드 선택 시 즉각적인 파일 개수 피드백 및 제한 초과 경고 메시지 추가 - 일괄 업로드 폼에 대상 바이트 프리셋 버튼과 총 파일 크기 미리보기를 추가하여 사용성을 개선했습니다. diff --git a/saas_web.py b/saas_web.py index 63265e94..4c123b85 100644 --- a/saas_web.py +++ b/saas_web.py @@ -114,7 +114,8 @@ async def require_api_key(request: Request, call_next): if configured_keys and not (request.method == "GET" and request.url.path == "/"): provided_key = request.headers.get("x-api-key", "") if not any( - hmac.compare_digest(provided_key, key) for key in configured_keys + hmac.compare_digest(provided_key.encode("utf-8"), key.encode("utf-8")) + for key in configured_keys ): return JSONResponse( status_code=401, diff --git a/tests/test_saas_web.py b/tests/test_saas_web.py index 3b57e033..d2d81196 100644 --- a/tests/test_saas_web.py +++ b/tests/test_saas_web.py @@ -741,6 +741,18 @@ def test_job_api_requires_key_when_configured(self): self.assertEqual(response.json(), {"error": "Invalid or missing API key"}) self.assertEqual(allowed.status_code, 404) + def test_non_ascii_keys_handled_safely(self): + with patch.dict(os.environ, {"CODEC_CARVER_API_KEYS": "secret-key"}): + # TestClient enforces ASCII strings, but we can pass bytes to mimic a raw HTTP request + # with non-ASCII content that hits the backend + response = client.post( + "/shrink", + files={"file": ("input.wav", io.BytesIO(b"dummy wav data"), "audio/wav")}, + data={"target_bytes": 0}, + headers={b"X-API-Key": "你好".encode("utf-8")}, + ) + self.assertEqual(response.status_code, 401) + def test_multiple_comma_separated_keys_all_valid(self): with patch.dict( os.environ, {"CODEC_CARVER_API_KEYS": "key-one,key-two,key-three"}