diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4cc49139..b3a62925 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,22 +3,12 @@ name: CI on: push: branches: [master] - paths-ignore: - - "docs/**" - - "*.md" pull_request: branches: [master] - paths-ignore: - - "docs/**" - - "*.md" permissions: contents: read -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - jobs: build: runs-on: ubuntu-latest diff --git a/.jules/sentinel.md b/.jules/sentinel.md index a885865d..967a7ab6 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -99,3 +99,7 @@ **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-01 - Input Validation for Path Length +**Vulnerability:** Path inputs without length limitations can lead to Out-Of-Memory (OOM) or Denial of Service (DoS) when processed. +**Learning:** Always explicitly validate unbounded input strings (e.g., path lengths) against a reasonable limit (e.g., 4096) before processing or relying on them in file system APIs. +**Prevention:** Add explicit `require(length <= LIMIT)` checks on input parameters at the boundary entry points (like `go()`). diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..93950c39 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -136,6 +136,7 @@ internal fun read_file_identity(file: File): FileIdentity { fun go(topDir: String, maxLevel: Int) { require(topDir.isNotBlank()) + require(topDir.length <= 4096) { "Directory path is too long" } require(!topDir.contains("..")) { "Path traversal sequences are not allowed." } // 보안 수정: symlink 검사를 우회하는 canonicalFile 대신 absoluteFile을 사용 // canonicalFile은 symlink를 대상 경로로 해석하여 이어지는 NOFOLLOW_LINKS 검사를 무력화합니다. diff --git a/src/test/kotlin/html4tree/MainTest.kt b/src/test/kotlin/html4tree/MainTest.kt index 5b76cc5d..f444daf1 100644 --- a/src/test/kotlin/html4tree/MainTest.kt +++ b/src/test/kotlin/html4tree/MainTest.kt @@ -127,6 +127,15 @@ class MainTest { } } + @Test + fun testGoRejectsExcessivelyLongPaths() { + val longPath = "a".repeat(4097) + val exception = assertFailsWith { + go(longPath, -1) + } + assertEquals("Directory path is too long", exception.message) + } + @Test fun testGoIgnoresHiddenFilesAndDirectories() { val hiddenFile = File(tempDir, ".hidden_file.txt")