From 231d391b9d21d14502d7cc36072bb4be72c42b7d Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Sat, 8 Aug 2026 03:42:40 +0000
Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM?=
=?UTF-8?q?]=20Fix=20Exception=20handling=20and=20empty=20dir=20name=20fal?=
=?UTF-8?q?lback?=
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 | 7 ++--
src/test/kotlin/html4tree/GlobTest.kt | 53 +++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 3 deletions(-)
create mode 100644 src/test/kotlin/html4tree/GlobTest.kt
diff --git a/.jules/sentinel.md b/.jules/sentinel.md
index cdf88010..3792ff4b 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-08 - [html4tree] 경로 및 입력 예외 처리 관련 보안 강화 (DoS 및 정보 노출 방지)
+**Vulnerability:** `getPathMatcher`가 던질 수 있는 `IllegalArgumentException` 누락에 의한 애플리케이션 크래시(DoS), 그리고 파일 시스템 루트(`""`) 처리 시 빈 문자열 노출로 인한 접근성 문제 및 대체 경로 사용 유도로 인한 정보 노출(Information Disclosure) 위험.
+**Learning:** `getPathMatcher`와 같은 기본 라이브러리는 예상치 못한 입력에 대해 문서화되지 않은 런타임 예외를 던질 수 있으며, 파일명 기반 처리는 루트 디렉토리 같은 엣지 케이스를 간과할 수 있습니다.
+**Prevention:** 사용자 제공 패턴 처리 시 `Exception`을 포괄적으로 잡아 크래시를 방지하고, 빈 파일명에 대해 `"/"` 같은 안전한 정적 대체값을 제공하여 파일 시스템 절대 경로가 노출되는 정보 누출을 방지하십시오.
diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt
index f52a1468..f7cd9ccb 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) {
}
}
}
@@ -326,6 +326,7 @@ fun process_dir(curr_dir: File, excludeSet: Set? = null, dirFiles: Array
val exclude: Set = excludeSet ?: process_ignore_file(curr_dir)
+ val dirName = curr_dir.name.ifEmpty { "/" }
val index_top = """
@@ -336,12 +337,12 @@ fun process_dir(curr_dir: File, excludeSet: Set? = null, dirFiles: Array
- ${curr_dir.getName().escapeHtml()}
+ ${dirName.escapeHtml()}
-