diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 6c61284..5bd7439 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. + +## 2024-07-24 - File Path Resolution leading to Path Traversal bypassing NOFOLLOW_LINKS +**Vulnerability:** Symlink path traversal via `File.canonicalFile` bypassing subsequent `NOFOLLOW_LINKS` checks. +**Learning:** In Java/Kotlin, resolving a `File` path using `.canonicalFile` inherently follows symlinks to return the final target location. When this resolved target is then passed to a function that supposedly restricts symlinks (like `Files.isDirectory(..., LinkOption.NOFOLLOW_LINKS)`), the check evaluates the target, not the original symlink. This entirely bypasses the intended security control. +**Prevention:** When intending to prevent following symlinks or strictly operate on the actual path provided without resolving targets, avoid using `File.canonicalFile`. Instead, normalize the path string logically using `.absoluteFile.toPath().normalize().toFile()`. This resolves `.` and `..` without implicitly following any symbolic links in the path. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8225e99 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# Changelog + +## Unreleased +- πŸ›‘οΈ Sentinel: [HIGH] `File.canonicalFile` λŒ€μ‹  `.absoluteFile.toPath().normalize().toFile()`을 μ‚¬μš©ν•˜μ—¬ 심볼릭 링크λ₯Ό 톡해 μ˜λ„ν•˜μ§€ μ•Šμ€ λ””λ ‰ν† λ¦¬λ‘œ μ΄λ™ν•˜λŠ” 경둜 탐색(Path Traversal) 취약점을 μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 2e2809f..2dcbfd2 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -23,7 +23,7 @@ fun main(args: Array) = Html4tree().main(args) fun go(topDir: String, maxLevel: Int) { require(topDir.isNotBlank()) - val top_dir = File(topDir).canonicalFile + val top_dir = File(topDir).absoluteFile.toPath().normalize().toFile() require(Files.isDirectory(top_dir.toPath(), LinkOption.NOFOLLOW_LINKS)) { "Top directory must be an existing non-symlink directory" } val ll = LinkedList()