diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 6c61284..31d1379 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -22,3 +22,8 @@ **Vulnerability:** Defense in Depth (CSP Missing) **Learning:** Even when inputs are properly escaped, statically generated HTML that displays file/directory structures should implement a Content Security Policy (CSP) to provide an extra layer of defense against potential XSS bypasses. **Prevention:** Include a strict CSP meta tag (e.g., `default-src 'none'; style-src 'unsafe-inline';`) in auto-generated HTML headers when external scripts or resources are not required. + +## 2026-07-02 - [Fix Path Traversal/Symlink Bypass in File Checking] +**Vulnerability:** 심볼릭 링크 디렉토리인지 검증하는 과정에서 `File.canonicalFile`을 사용하면, JVM/OS가 심볼릭 링크를 대상 경로(실제 디렉토리)로 미리 해석(resolve)해 버립니다. 그 결과 `Files.isDirectory(..., LinkOption.NOFOLLOW_LINKS)`가 심볼릭 링크 자체가 아닌 실제 디렉토리를 검사하게 되어 심볼릭 링크 검증을 우회하는 보안 취약점이 발생했습니다. +**Learning:** `canonicalFile`은 모든 심볼릭 링크를 해석하고 정규화된 절대 경로를 반환합니다. 심볼릭 링크 자체의 속성을 검사해야 할 때(예: 심볼릭 링크를 허용하지 않거나, 경로 탐색을 방지해야 하는 경우) `canonicalFile`을 사용하면 검증 로직이 무효화될 수 있습니다. +**Prevention:** 심볼릭 링크 검증 시에는 경로의 상대성만 해결하고 심볼릭 링크를 해석하지 않는 `Path.toAbsolutePath().normalize()`을 사용해야 합니다. 그 후 `LinkOption.NOFOLLOW_LINKS`와 같은 옵션을 사용하여 안전하게 파일 시스템 속성을 검사해야 합니다. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 2e2809f..c76f043 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -23,7 +23,8 @@ fun main(args: Array) = Html4tree().main(args) fun go(topDir: String, maxLevel: Int) { require(topDir.isNotBlank()) - val top_dir = File(topDir).canonicalFile + // 보안 취약점 수정: canonicalFile 대신 toPath().toAbsolutePath().normalize().toFile()을 사용하여 심볼릭 링크를 미리 해석하지 않도록 함. (경로 탐색 취약점 방지) + val top_dir = File(topDir).toPath().toAbsolutePath().normalize().toFile() require(Files.isDirectory(top_dir.toPath(), LinkOption.NOFOLLOW_LINKS)) { "Top directory must be an existing non-symlink directory" } val ll = LinkedList()