From 6e5d6efce3dbdbc53e1d02009027c8c7f54ec542 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 24 Sep 2026 20:54:04 +0000 Subject: [PATCH 1/8] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM?= =?UTF-8?q?]=20Fix=20BiDi=20spoofing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 파일 및 디렉토리 이름 출력 시 유니코드 양방향(BiDi) 텍스트 제어 문자로 인한 Spoofing(예: 확장자 속이기) 방지를 위해 이스케이핑 및 격리(Isolate) 처리를 추가했습니다. --- .jules/sentinel.md | 5 +++++ src/main/kotlin/html4tree/main.kt | 9 +++++---- src/test/kotlin/html4tree/MainTest.kt | 9 +++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index a885865d..0d12e9f8 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-09-24 - BiDi Spoofing / Trojan Source Prevention +**Vulnerability:** 파일 및 디렉토리 이름이 디렉토리 목록 화면에 표시될 때, 공격자가 악의적으로 유니코드 양방향 텍스트(BiDi) 제어 문자인 Right-to-Left Override(\u202E)를 삽입하여 확장자를 속일 수 있는(BiDi Spoofing) 취약점이 있었습니다. 이로 인해 악성 실행 파일이 안전한 문서 파일인 것처럼 보이게 할 수 있었습니다. +**Learning:** HTML 이스케이핑만으로는 충분하지 않습니다. 파일 이름 같은 사용자 입력이 브라우저에서 방향성을 띄지 않고 있는 그대로 안전하게 출력되려면, 제어 문자를 명시적으로 보여주는 처리와 함께 텍스트 방향을 격리(Isolate)해야 한다는 것을 배웠습니다. +**Prevention:** HTML 이스케이프 함수 내에서 `\u202E` 문자를 문자열 `\\u202E`로 렌더링되게 치환하고, HTML 내에서 사용자 입력이 들어가는 부분을 First Strong Isolate (`⁨`)와 Pop Directional Isolate (`⁩`) 기호로 감싸 렌더링 방향이 왜곡되지 않게 보호해야 합니다. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..42bc23b9 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -243,6 +243,7 @@ fun String.escapeHtml(): String { '"' -> """ '\'' -> "'" '`' -> "`" + '\u202E' -> "\\u202E" else -> null } if (replacement != null) { @@ -421,12 +422,12 @@ fun process_dir(curr_dir: File, excludeSet: Set? = null, dirFiles: Array - ${directoryName.escapeHtml()} - 디렉토리 목록 + ⁨${directoryName.escapeHtml()}⁩ - 디렉토리 목록
-

${directoryName.escapeHtml()}

+

⁨${directoryName.escapeHtml()}⁩

")) assertTrue(htmlContent.contains("상위 디렉토리로 이동")) assertTrue(htmlContent.contains("title=\"상위 디렉토리로 이동\"")) + assertTrue(htmlContent.contains("aria-label=\"상위 디렉토리로 이동\"")) assertTrue(htmlContent.contains("aria-hidden=\"true\"")) assertTrue(htmlContent.contains("파일")) assertTrue(htmlContent.contains("title=\"⁨file1.txt⁩ 파일\"")) + assertTrue(htmlContent.contains("aria-label=\"⁨file1.txt⁩ 파일\"")) assertTrue(htmlContent.contains("디렉토리")) assertTrue(htmlContent.contains("title=\"⁨subdir⁩ 디렉토리\"")) + assertTrue(htmlContent.contains("aria-label=\"⁨subdir⁩ 디렉토리\"")) assertTrue(htmlContent.contains("file1.txt")) assertTrue(htmlContent.contains("subdir/")) assertTrue(htmlContent.contains("📁")) From d1fb07ee0ff023872cb4fb7171e5ca93e87277f9 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 27 Sep 2026 04:59:08 +0000 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM?= =?UTF-8?q?]=20Fix=20BiDi=20spoofing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 파일 및 디렉토리 이름 출력 시 유니코드 양방향(BiDi) 텍스트 제어 문자로 인한 Spoofing(예: 확장자 속이기) 방지를 위해 이스케이핑 및 격리(Isolate) 처리를 추가했습니다. 추가로, 스크린 리더 등 접근성을 위한 `aria-label`도 올바르게 적용되도록 개선했습니다.