From fab6b7f55df85ac438257d0a3f257b44de2bb2b8 Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Fri, 7 Aug 2026 03:45:34 +0000
Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?=
=?UTF-8?q?Fix=20DoS=20vulnerability=20in=20glob=20pattern=20parsing?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.jules/sentinel.md | 5 +++++
src/main/kotlin/html4tree/main.kt | 2 +-
src/test/kotlin/html4tree/MainTest.kt | 15 +++++++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/.jules/sentinel.md b/.jules/sentinel.md
index cdf88010..34d5defd 100644
--- a/.jules/sentinel.md
+++ b/.jules/sentinel.md
@@ -88,3 +88,8 @@
**Vulnerability:** CSP 해시 불일치로 인한 인라인 스타일 차단
**Learning:** 브라우저는 인라인 스크립트와 스타일의 내부 텍스트(공백과 줄바꿈 포함)를 정확하게 해싱하여 Content-Security-Policy(CSP) 해시와 비교합니다. Kotlin의 멀티라인 문자열(`"""`)을 사용하여 템플릿에 콘텐츠를 주입할 때 암묵적인 여백이나 줄바꿈이 추가되면 최종 HTML 문자열이 변경되어 CSP 해시가 무효화됩니다.
**Prevention:** 콘텐츠를 해싱하기 전에 `.trimIndent()`를 적용하여 원본 문자열을 정규화하고, HTML 템플릿에 주입할 때 ``와 같이 공백 없이 주입하여 해시가 완벽하게 일치하도록 해야 합니다.
+
+## 2026-08-07 - [MEDIUM] FileSystem getPathMatcher 예외 처리 미흡으로 인한 DoS
+**Vulnerability:** 사용자가 조작 가능한 .html4ignore 내의 glob 패턴 파싱 중 특정 잘못된 구문(예: 빈 문자열, 특정 특수 문자)으로 인해 java.lang.IllegalArgumentException 또는 기타 예외가 발생하여, 전체 프로세스가 중단(DoS)될 수 있습니다.
+**Learning:** Java NIO의 getPathMatcher 메서드는 PatternSyntaxException 외에도 IllegalArgumentException과 같은 다른 런타임 예외를 발생시킬 수 있습니다. 외부 입력을 처리할 때는 포괄적인 예외 처리가 필요합니다.
+**Prevention:** glob 패턴 파싱 및 getPathMatcher 호출 시 포괄적인 예외 처리를 사용하여 예상치 못한 런타임 예외로 인한 애플리케이션 충돌을 방지해야 합니다.
diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt
index f52a1468..8429ca10 100644
--- a/src/main/kotlin/html4tree/main.kt
+++ b/src/main/kotlin/html4tree/main.kt
@@ -274,7 +274,7 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array? = null): S
if (pattern.isNotEmpty() && pattern.length <= 100) {
try {
ignored_matchers.add(java.nio.file.FileSystems.getDefault().getPathMatcher("glob:$pattern"))
- } catch (_: java.util.regex.PatternSyntaxException) {
+ } catch (_: Exception) {
}
}
}
diff --git a/src/test/kotlin/html4tree/MainTest.kt b/src/test/kotlin/html4tree/MainTest.kt
index 83739c9c..30ec995c 100644
--- a/src/test/kotlin/html4tree/MainTest.kt
+++ b/src/test/kotlin/html4tree/MainTest.kt
@@ -581,6 +581,21 @@ class MainTest {
assertTrue(excluded.contains("index.html"))
}
+ @Test
+ fun testProcessIgnoreFileIllegalArgumentException() {
+ val ignoreFile = File(tempDir, ".html4ignore")
+ // '[' throws PatternSyntaxException, '\0' throws IllegalArgumentException
+ ignoreFile.writeText("a\u0000b\n\n*.log")
+
+ File(tempDir, "test.log").createNewFile()
+ File(tempDir, "test.txt").createNewFile()
+
+ val excluded = process_ignore_file(tempDir, null)
+ assertTrue(excluded.contains("test.log"))
+ assertFalse(excluded.contains("test.txt"))
+ assertTrue(excluded.contains("index.html"))
+ }
+
@Test
fun testProcessIgnoreFileDosProtection() {
val ignoreFile = File(tempDir, ".html4ignore")