From 4c98c9bda9043f5ec0662abcf63e9d599aec55c1 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 3 Sep 2026 21:47:28 +0000 Subject: [PATCH] =?UTF-8?q?=EB=B3=B4=EC=95=88:=20PdfReader=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=ED=8F=AC=EA=B4=84=EC=A0=81=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EA=B9=85=20=EC=B6=94=EA=B0=80=20(DoS=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/sentinel.md | 5 +++++ src/newsdom_api/main.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 2b5d819c..4b6a6327 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. + +## 2024-05-31 - [구조적 검증 중 발생하는 예외를 포괄적으로 처리하여 DoS 방지] +**Vulnerability:** `PdfReader`와 같은 구조적 검증 라이브러리는 비정상적인 파일에 대해 `MemoryError`나 `TypeError` 같은 처리되지 않은 예외를 발생시켜 500 오류 및 서비스 거부(DoS)를 유발할 수 있습니다. +**Learning:** 기형적인 PDF는 파싱 라이브러리 깊은 곳에서 예측하기 어려운 다양한 예외를 유발할 수 있으므로 특정 예외만 잡는 것은 불충분합니다. +**Prevention:** 외부 라이브러리를 통해 복잡한 파일 구조를 검증할 때는 `except Exception:`을 사용하여 모든 예외를 포괄적으로 처리하고, 실제 문제 원인을 파악할 수 있도록 로그로 기록(`LOGGER.error`)한 후 안전한 415 클라이언트 오류로 변환해야 합니다. diff --git a/src/newsdom_api/main.py b/src/newsdom_api/main.py index f61aafc2..dbe71715 100644 --- a/src/newsdom_api/main.py +++ b/src/newsdom_api/main.py @@ -193,7 +193,8 @@ def _validate_pdf_structure(file_path: Path) -> None: reader = PdfReader(file_path, strict=True) if len(reader.pages) < 1: raise ValueError("PDF has no pages") - except (PdfReadError, RecursionError, ValueError, OverflowError): + except Exception as exc: + LOGGER.error("PDF structural validation failed", exc_info=exc) raise HTTPException( status_code=415, detail=UNSUPPORTED_MEDIA_DETAIL,