diff --git a/.jules/sentinel.md b/.jules/sentinel.md index a885865d..238c06b5 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`). + +## 2026-09-16 - [DoS/OOM 방지] 입력 경로 길이 제한 누락 +**Vulnerability:** 파일 시스템 API에 전달되는 사용자 제공 디렉토리 경로 문자열(`topDir`)에 대한 최대 길이 검증이 누락되어 악의적으로 긴 문자열 입력 시 DoS(서비스 거부) 및 OOM(메모리 부족) 취약점이 발생할 수 있었습니다. +**Learning:** 제한 없이 사용자 입력을 허용하고 이를 비싼 연산(예: `File.absoluteFile.toPath().normalize()`)에 전달할 경우 애플리케이션 리소스를 고갈시킬 수 있습니다. +**Prevention:** 사용자 제공 경로나 문자열을 처리할 때는 파일 시스템 상호작용 전에 항상 명시적인 최대 길이 경계(예: `require(topDir.length <= 4096)`)를 설정하여 방어하십시오. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..3d5731c1 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) { "Directory path exceeds maximum allowed length of 4096 characters" } 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..88e63972 100644 --- a/src/test/kotlin/html4tree/MainTest.kt +++ b/src/test/kotlin/html4tree/MainTest.kt @@ -596,6 +596,12 @@ class MainTest { go(" ", -1) } + @Test(expected = IllegalArgumentException::class) + fun testGoRejectsExcessivelyLongPath() { + val longPath = "a".repeat(4097) + go(longPath, -1) + } + @Test fun testUrlEncodePathUnreserved() { assertEquals("-._~", "-._~".urlEncodePath())