diff --git a/.jules/sentinel.md b/.jules/sentinel.md index a885865d..e42582d6 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-25 - BiDi Text Spoofing 방지 +**Vulnerability:** 파일명에 RTL(Right-to-Left) 오버라이드 등 유니코드 양방향(BiDi) 제어 문자가 포함될 경우 확장자가 위조되는 취약점이 발견되었습니다. +**Learning:** BiDi 오버라이드는 시각적으로 위험한 파일(예: `.exe`)을 무해한 파일(예: `.txt`)처럼 보이게 만들 수 있습니다. HTML을 렌더링할 때 사용자 통제 영역이 이를 적절히 처리하거나 무효화하지 않으면 XSS 또는 악성 다운로드를 유도할 수 있습니다. +**Prevention:** HTML 이스케이프 과정에서 유니코드 BiDi 제어 문자(예: `\u202E`)를 이스케이프(예: `\\u202E`)하여 무력화하고, 렌더링된 요소(예: ``, `<a>`의 텍스트)를 `⁨`(FSI) 및 `⁩`(PDI)로 감싸 텍스트 방향성이 문서 내 다른 요소에 영향을 미치지 않도록 격리해야 합니다. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..3517b06d 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -243,6 +243,15 @@ fun String.escapeHtml(): String { '"' -> """ '\'' -> "'" '`' -> "`" + '\u202A' -> "\\u202A" + '\u202B' -> "\\u202B" + '\u202C' -> "\\u202C" + '\u202D' -> "\\u202D" + '\u202E' -> "\\u202E" + '\u2066' -> "\\u2066" + '\u2067' -> "\\u2067" + '\u2068' -> "\\u2068" + '\u2069' -> "\\u2069" else -> null } if (replacement != null) { @@ -421,12 +430,12 @@ fun process_dir(curr_dir: File, excludeSet: Set<String>? = null, dirFiles: Array <!-- 보안 향상: 리퍼러를 통한 디렉토리 경로 노출 방지 --> <meta name="referrer" content="no-referrer"> <meta name="robots" content="noindex, nofollow"> - <title>${directoryName.escapeHtml()} - 디렉토리 목록 + ⁨${directoryName.escapeHtml()}⁩ - 디렉토리 목록
-

${directoryName.escapeHtml()}

+

⁨${directoryName.escapeHtml()}⁩