diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 06bd05a7..6c612841 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -17,3 +17,8 @@ **Vulnerability:** The application could crawl symlink directories, accept a symlink as the top-level directory, and walk deeper than the requested max level before deciding not to render. **Learning:** `File.listFiles()` returns null (not empty) on unreadable directories. Directory crawlers must reject symlink roots, skip symlink children, and avoid enqueueing paths deeper than the configured traversal limit. **Prevention:** Use `java.nio.file.Files.isSymbolicLink(file.toPath())` for root and child directory checks, gracefully handle `null` arrays from `listFiles()` and `list()`, and only enqueue child directories when the current level is still below `maxLevel`. + +## 2024-06-28 - [html4tree] Static HTML Generation Security +**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. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 30a6ca79..66efb40e 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -158,6 +158,8 @@ fun process_dir(curr_dir: File){ + + ${curr_dir.getName().escapeHtml()} ${css} diff --git a/src/test/kotlin/html4tree/MainTest.kt b/src/test/kotlin/html4tree/MainTest.kt index 5d5611c0..68e56b15 100644 --- a/src/test/kotlin/html4tree/MainTest.kt +++ b/src/test/kotlin/html4tree/MainTest.kt @@ -156,6 +156,8 @@ class MainTest { assertTrue(htmlContent.contains("subdir/")) assertTrue(htmlContent.contains("📁")) assertFalse(htmlContent.contains("test.ignore")) + assertTrue(htmlContent.contains("Content-Security-Policy")) + assertTrue(htmlContent.contains("default-src 'none'; style-src 'unsafe-inline';")) } @Test