Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 16 additions & 26 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
## 2024-06-21 - 루프 내 정규식 컴파일
**학습:** Kotlin에서 무시 파일을 처리할 때 파일 반복 루프 내에서 정규식(`.toRegex()`)을 컴파일하는 것은 O(N * M)의 심각한 성능 병목을 일으킵니다 (N 파일 * M 규칙).
**조치:** 불필요한 정규식 재컴파일을 피하기 위해 항상 파일 반복 루프 외부에서 문자열 규칙을 컴파일된 `Regex` 객체로 매핑합니다 (O(M) 컴파일).
## 2024-06-21 - Regex Compilation in Loops
**Learning:** In Kotlin, compiling regular expressions (`.toRegex()`) inside a loop over files is a significant O(N * M) performance bottleneck when processing ignore files (N files * M rules).
**Action:** Always map string rules to compiled `Regex` objects outside of the file iteration loop (O(M) compilation) to avoid unnecessary regex re-compilations.

## 2024-05-24 - 루프 내 할당 핫 패스
**학습:** 디렉토리 항목을 렌더링할 때 반복적인 문자열 연결과 리스트 기반 제외 조회를 사용하면 대규모 디렉토리에서 불필요한 할당 및 조회 비용이 발생합니다.
**조치:** 항목 렌더링에 `StringBuilder`를 사용하고 제외된 파일 이름에 대해 `Set`을 사용합니다.
## 2024-05-24 - Loop Allocation Hot Paths
**Learning:** Rendering directory entries with repeated string concatenation and list-based exclusion lookups creates avoidable allocation and lookup cost in large directories.
**Action:** Use `StringBuilder` for entry rendering and a `Set` for excluded file names.

## 2024-07-26 - 중간 문자열 할당
**학습:** Kotlin에서 문자열에 연결된 `.replace()` 호출 (예: HTML 이스케이프)은 각 단계에서 중간 문자열을 할당하여 요소가 많은 핫 패스에서 성능 및 가비지 컬렉션에 큰 영향을 미칩니다.
**조치:** 연결된 `.replace()` 호출을 문자를 한 번만 반복하는 단일 패스 루프로 바꾸고, 변환된 출력을 추가하기 위해 `StringBuilder`를 지연 초기화합니다.

## 2024-07-08 - URL 인코딩 문자열 할당 병목
**학습:** 핫 패스 루프 내에서 예약된 바이트당 최대 3개의 문자열을 할당하는 `byte.toString(16).padStart(2, '0').toUpperCase()`는 상당한 GC 압력을 유발합니다. 이는 디렉토리 크롤러에서 대규모 문자열이나 수많은 파일을 처리할 때 Kotlin에서 흔히 볼 수 있는 위험한 안티 패턴입니다.
**조치:** 중간 문자열 생성을 완전히 피하기 위해 포맷된 16진수 출력을 작성할 때 연결된 문자열 연산을 직접 문자 매핑 및 비트 연산(`ushr`, `and`)으로 바꿉니다. 10 미만 및 9 초과의 16진수 값을 모두 포괄하는 테스트 입력을 통해 100% 브랜치 커버리지를 보장합니다.

## 2026-07-10 - 저렴한 메모리 내 검사 전 비싼 OS stat 호출
**학습:** Kotlin/Java에서 `java.nio.file.Files`를 통해 파일 속성 (예: `isDirectory` 또는 `isSymbolicLink`)을 확인하려면 `Path` 객체를 할당해야 하며 비싼 네이티브 OS stat 호출을 수행합니다. 파일 목록을 처리할 때 파일 시스템을 건드리는 메서드를 호출하기 전에 제외 목록 (저렴한 메모리 내 문자열 연산 사용)과 비교하여 파일 시스템 검사를 단축합니다.
**조치:** `Files.isDirectory` 및 `Files.isSymbolicLink`를 호출하기 전에 `exclude` 세트를 확인하도록 조건문을 재배열했습니다.


## 2026-07-12 - 이중 루프 내 패턴 매칭 조기 종료 (Short-Circuit)
**학습:** 무시할 파일(ignore patterns)을 확인할 때, 각 파일에 대해 모든 패턴을 순회(`forEach`)하는 것은 비효율적입니다. 파일이 하나의 패턴에 매칭되어 제외 목록에 추가되면 나머지 패턴을 확인할 필요가 없습니다. 이를 조기 종료(Short-circuit)하지 않으면 불필요한 O(N * M) 정규식/패턴 매칭 평가가 발생합니다.
**조치:** 무시 목록 평가 등 조건을 만족할 때 더 이상 확인이 필요 없는 경우에는 `forEach` 대신 일반 `for` 루프와 `break`를 사용하거나 `any`를 활용하여 연산을 단축합니다.

## 2024-07-28 - 디렉토리 목록 불필요한 정렬 오버헤드
**학습:** 디렉토리 목록(`list()` 또는 `listFiles()`)을 단순히 필터링하여 `Set`에 추가하는 경우처럼 특정 순서가 필요하지 않은 작업에서 `.sorted()`를 호출하면 불필요한 O(N log N) 오버헤드가 발생합니다.
**조치:** `Set`과 같은 순서에 무관한 자료구조에 요소를 추가하기 위한 필터링 작업에서는 디렉토리 목록에서 `.sorted()` 호출을 제거하여 성능을 최적화합니다.
## 2024-07-26 - Intermediate String Allocations
**Learning:** Chained `.replace()` calls on strings in Kotlin (e.g. for HTML escaping) allocate an intermediate String at each step, significantly impacting performance and garbage collection on hot paths with many elements.
**Action:** Replace chained `.replace()` calls with a single-pass loop that iterates over characters once, lazily initializing a `StringBuilder` to append the transformed output.
## 2024-07-08 - URL Encoding String Allocation Bottleneck
**Learning:** `byte.toString(16).padStart(2, '0').toUpperCase()` inside a loop allocating up to 3 strings per reserved byte in a hot path causes significant GC pressure. This is a common but dangerous anti-pattern in Kotlin when processing large strings or numerous files in directory crawlers.
**Action:** Replace chained string operations with direct character mapping and bitwise operations (`ushr`, `and`) when building formatted hex output, which avoids intermediate string creation entirely. Ensure 100% branch coverage with test inputs spanning both < 10 and > 9 hex values.
## 2026-07-10 - Expensive OS stat calls before cheap in-memory checks\n**Learning:** In Kotlin/Java, checking file properties (like `isDirectory` or `isSymbolicLink`) via `java.nio.file.Files` requires allocating `Path` objects and performs expensive native OS stat calls. When processing file listings, always short-circuit filesystem checks by testing against exclusion lists (using cheap in-memory string operations) before calling methods that touch the filesystem.\n**Action:** Re-ordered conditionals to check `exclude` sets before invoking `Files.isDirectory` and `Files.isSymbolicLink`.
## 2024-07-11 - [Eliminating Redundant Directory Listings]
**Learning:** In nested file processing functions like `process_dir` and `process_ignore_file`, executing `curr_dir.listFiles()` repeatedly for the same directory is highly inefficient and creates expensive duplicate OS syscalls.
**Action:** Always hoist I/O intensive listing operations like `listFiles()` to the highest appropriate scope and pass the result as a parameter to child functions rather than re-evaluating it.
7 changes: 0 additions & 7 deletions .jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,3 @@
## 2026-07-10 - ARIA Label Language Matching
**Learning:** Screen readers rely on the document's language attribute (`lang="ko"`) to select the appropriate pronunciation engine. If semantic descriptors like `aria-label` are provided in a language different from the document language (e.g., English text in a Korean document), they may be mispronounced or skipped entirely, breaking accessibility.
**Action:** Always ensure that `aria-label`, `alt` text, and other hidden semantic text strings match the language specified in the document's `<html lang="...">` tag for proper localization and screen reader compatibility.
## 2026-07-11 - Safari VoiceOver List Semantics Fix
**Learning:** Using `list-style: none` or `list-style-type: none` in CSS causes Safari (VoiceOver) to remove list semantics entirely, which harms accessibility for screen reader users trying to navigate directory listings.
**Action:** Always explicitly add `role="list"` to `<ul>` or `<ol>` elements when removing their default list styling to preserve accessibility semantics across all browsers.

## 2026-07-12 - Inline Colors vs Dark Mode
**Learning:** Hardcoded inline colors (like `color: #666`) fail to adapt in dark mode because they bypass CSS media queries and cannot be easily overridden without `!important`, causing text legibility issues on dark backgrounds.
**Action:** Use `opacity: 0.7` instead of hardcoded hex values for muted text to dynamically inherit theme colors and ensure legibility across all color schemes.
16 changes: 4 additions & 12 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
**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] 정적 HTML 생성 보안
**Vulnerability:** 심층 방어 누락 (CSP 누락)
**Learning:** 입력값이 적절히 이스케이프 되더라도, 파일/디렉토리 구조를 표시하는 정적 생성 HTML은 잠재적인 XSS 우회 공격에 대비하여 추가적인 방어 계층을 제공하는 콘텐츠 보안 정책(CSP)을 반드시 구현해야 합니다.
**Prevention:** 외부 스크립트나 리소스가 필요하지 않은 경우 자동 생성되는 HTML 헤더에 엄격한 CSP 메타 태그(예: `default-src 'none'; style-src 'nonce-...'; base-uri 'none'; form-action 'none';`)를 포함하고, 스타일 블록에는 일회성 nonce를 부여하십시오.
## 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.

## 2024-05-31 - [CRITICAL] 심볼릭 링크 검사 우회 취약점 (canonicalFile)
**Vulnerability:** `File(path).canonicalFile`를 사용하여 심볼릭 링크 여부를 검사하면, `canonicalFile` 함수 내부에서 심볼릭 링크를 이미 대상(target) 파일의 실제 경로로 해석(resolve)해 버리기 때문에, 이후에 진행되는 `Files.isDirectory(..., LinkOption.NOFOLLOW_LINKS)` 등의 심볼릭 링크 제한 검사가 완전히 무력화되는 취약점이 발견되었습니다.
Expand All @@ -45,11 +45,3 @@
**Vulnerability:** The `.html4ignore` parser still allowed excessively large files and root-directory crawls could generate unbounded filesystem output.
**Learning:** Local CLI configuration inputs and traversal roots need explicit resource ceilings, not only syntactic validation.
**Prevention:** Limit `.html4ignore` file size, parsed line count, compiled pattern count, and regex length; reject filesystem root traversal using `File.parentFile != null`.
## 2024-07-11 - [.html4ignore 파일의 ReDoS 취약점 수정 (Glob 패턴 적용)]
**Vulnerability:** [사용자가 제공한 `.html4ignore` 패턴을 직접 정규표현식으로 컴파일하여 발생하는 ReDoS(정규표현식 서비스 거부) 취약점 발견.]
**Learning:** [필터링 패턴으로 정규표현식을 직접 노출하면 악의적으로 조작된 긴 문자열이나 복잡한 패턴을 통해 애플리케이션의 리소스를 고갈시킬 수 있음.]
**Prevention:** [사용자 입력 패턴은 정규표현식으로 변환하기 전 `java.nio.file.FileSystems.getDefault().getPathMatcher("glob:$pattern")`와 같은 안전한 Glob 매칭 방식을 사용해야 함.]
## 2024-07-12 - [html4tree] Unhandled File/Directory Permissions causing DoS
**Vulnerability:** When encountering an unreadable `.html4ignore` file or a directory without write permissions, an unhandled `java.io.FileNotFoundException` or `java.nio.file.AccessDeniedException` was thrown, respectively. This causes the entire crawler to crash (DoS) when encountering files/directories with restricted permissions.
**Learning:** Application processes that recursively scan filesystem directories must gracefully handle permission denied exceptions to ensure that one inaccessible node does not halt the entire scanning/processing operation.
**Prevention:** Check `.canRead()` before attempting to parse configuration/ignore files, and wrap file writing operations in `try-catch` blocks to securely handle `AccessDeniedException` or other `IOException`s, failing gracefully (Fail Securely) rather than crashing the application.
Loading
Loading