diff --git a/.jules/sentinel.md b/.jules/sentinel.md index a885865d..32bd727c 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -99,3 +99,8 @@ **Root cause:** The protected implementation added canonical names to the exclusion set but did not compare each observed directory entry through a locale-stable normalized key. **Prevention:** Build one `Locale.ROOT` lowercase set from the canonical sensitive names, compare every observed name against it, and add the original spelling to the exclusion set so downstream exact membership remains correct. **Evidence:** `testProcessIgnoreFileTreatsSensitiveNamesCaseInsensitively` failed on test-only commit `472b916cd40f70693c4e1eb48956042a25353feb` (CI run `31469596932`) and passed with the source fix at `bb113d858ccfc42ddaecf6729749b238e5ade2d0` (CI run `31469921661`). + +## 2024-10-25 - [보통] 무제한 디렉토리 경로 입력으로 인한 DoS 취약점 완화 +**Vulnerability:** 파일 시스템 작업(가령 절대 경로 해석 및 디렉토리 크롤링)에 제약 없는 문자열이 입력 경로로 들어갈 경우 이를 처리하다가 메모리 부족(OOM)이나 과도한 I/O 처리로 인한 서비스 거부(DoS)가 발생할 수 있습니다. +**Learning:** 시스템의 파일 접근 API를 호출하기 전에 외부 입력을 기반으로 하는 디렉토리 경로는 합리적인 최대 길이를 초과하지 않도록 검증해야 합니다. +**Prevention:** 크롤링이나 접근 대상 경로(예: `topDir`)의 길이를 제한(예: 4096자)하여 경로 정규화 등 리소스 소모적인 작업이 방지되도록 하십시오. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..6f7d6381 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -136,6 +136,7 @@ internal fun read_file_identity(file: File): FileIdentity { fun go(topDir: String, maxLevel: Int) { require(topDir.isNotBlank()) + require(topDir.length <= 4096) { "Top directory path is too long." } require(!topDir.contains("..")) { "Path traversal sequences are not allowed." } // 보안 수정: symlink 검사를 우회하는 canonicalFile 대신 absoluteFile을 사용 // canonicalFile은 symlink를 대상 경로로 해석하여 이어지는 NOFOLLOW_LINKS 검사를 무력화합니다. diff --git a/src/test/kotlin/html4tree/MainTest.kt b/src/test/kotlin/html4tree/MainTest.kt index 5b76cc5d..7d282f1c 100644 --- a/src/test/kotlin/html4tree/MainTest.kt +++ b/src/test/kotlin/html4tree/MainTest.kt @@ -596,6 +596,11 @@ class MainTest { go(" ", -1) } + @Test(expected = IllegalArgumentException::class) + fun testGoTopDirTooLong() { + go("a".repeat(4097), -1) + } + @Test fun testUrlEncodePathUnreserved() { assertEquals("-._~", "-._~".urlEncodePath())