Security
- [Critical] Path traversal in
tee show— Thelean-ctx tee show <filename>CLI command accepted path separators and..in the filename argument, allowing reads of arbitrary files outside the tee log directory. Now enforces strict basename-only validation. - [Critical] Python/Shell injection via
intentparameter — Thectx_executetool interpolated theintentparameter raw into generated Python and shell scripts, allowing code injection through crafted intent strings. Now sanitized to alphanumeric characters only (max 200 chars). - [Critical] CSPRNG failure silently ignored — Two
getrandom::fillcalls (token generation + CSP nonce) silently discarded errors, which could result in predictable all-zero tokens/nonces. Now panics on CSPRNG failure to guarantee cryptographic safety. - [Critical] Dashboard path traversal bypass — The
/api/compression-demoendpoint allowed absolute paths to bypasspathjailfilesystem jail. All paths now go throughjail_pathunconditionally. - [Critical] MCP stdio integer overflow — Malicious
Content-Lengthheaders could cause integer overflow in frame length calculation, leading to unbounded memory allocation. Now useschecked_addwith strict size cap. - [High] Token exposure on loopback — Anonymous loopback GET requests to the dashboard received the auth token injected into HTML, allowing any local process to steal it. Now requires explicit
?token=query parameter. - [High] Nonce-based CSP replaces
unsafe-inline— Dashboard Content-Security-Policy upgraded fromscript-src 'unsafe-inline'to per-response cryptographic nonce, eliminating XSS via inline script injection. - [High] Panic payloads leaked to MCP clients — Tool panics returned full panic messages (potentially containing secrets/paths) to clients. Now returns generic error; details logged server-side only.
- [High]
ctx_executeoutput not redacted — Output fromctx_executebypassed the redaction engine, potentially leaking secrets. Now appliesredact_text_if_enabledlikectx_shell. - [High] Cross-project data access via
ctx_share— Shared agent data was stored in a flat directory, allowing agents from different projects to read each other's data. Now scoped underproject_hashsubdirectory. - [High] PowerShell command interpolation — On Windows, PowerShell commands were interpolated into script strings. Now writes to temp file and executes via
-File. - [High] Cloud server error information leak —
internal_errorhelper returned raw database/OS error strings to HTTP clients. Now returns generic{"error":"internal_error"}. - [High] SSE subscriber cap enforced — The 64-subscriber-per-channel cap previously only logged a warning but still allowed new subscriptions. Now returns
Noneand falls back to dead channel, preventing resource exhaustion. - [High] Rust sandbox inherited full environment — The
execute_rustfunction (rustc + compiled binary) did not strip inherited environment variables, exposing secrets and enablingLD_PRELOAD-style attacks. Now applies the sameenv_clear()+ allowlist as other sandbox runtimes. - [Medium] Argon2id password hashing — Cloud server passwords migrated from salted SHA-256 to Argon2id with legacy fallback for existing hashes.
- [Medium] SQLite busy_timeout — Added 5-second busy_timeout to all SQLite connections to prevent
SQLITE_BUSYerrors under contention. - [Medium] ReDoS mitigation for filter rules — Both runtime and validation paths for user-authored filter TOML patterns now use
RegexBuilderwith 1 MiB DFA size limit. - [Medium] Context summary redaction —
/v1/context/summaryendpoint now redacts events atSummarylevel before aggregation, preventing leakage of sensitive knowledge keys/categories. - [Medium] A2A handoff error sanitization — Parse and write errors no longer include OS-level details or filesystem paths in HTTP responses.
- [Medium]
ctx_searchandctx_treeparameter clamping —max_resultscapped at 500,depthcapped at 10 to prevent resource exhaustion. - [Medium]
ctx_shellcwd fail-closed — Invalid working directory now returns error instead of silently falling back to process cwd. - [Medium] Community detection graceful degradation — All SQLite
unwrap()calls incommunity.rsreplaced with proper error handling returning empty graphs instead of panicking. - [Medium] Defense-in-depth path canonicalization —
read_file_lossynow verifies canonical paths stay within project root (warning-only layer behind primaryjail_pathenforcement). - [Medium] Sandbox environment isolation —
ctx_executesubprocesses now start withenv_clear()+ explicit allowlist (PATH, HOME, LANG, TERM, TMPDIR) instead of inheriting all parent environment variables. - [Medium] Hook temp file hardening — Temp directory for hook redirects now has
chmod 700(Unix), and filenames include PID scoping to prevent symlink races. - [Medium] PowerShell temp file cleanup —
.ps1temp files are now deleted on all exit paths (success, spawn error, wait error). - [Medium]
ctx_executetemp file lifecycle —.dattemp files are now cleaned up by Rust after sandbox execution (regardless of script success), with file size validation before processing. - [Medium]
/healthrate limiting — Health endpoint no longer bypasses rate limiter and concurrency semaphore, preventing use as amplification oracle. - [Low]
validate_filter_fileregex bounds — Validation path now uses boundedRegexBuildermatching runtime behavior. - [Low] Corrected
check_secret_path_for_tooltool name — Changed hardcoded"ctx_read"to"resolve_path"for accurate policy logging.
Fixed
- Structural output protection —
git diff,git show,git blame,git log -p,git stash show,diff,colordiff,icdiff, anddeltaoutput was being mangled by up to three compression layers (pattern compression + terse pipeline + generic compressors like log_dedup/truncation). These commands now get a dedicated fast path: only the specific pattern compressor runs (light cleanup: stripindexheaders, limit context lines), all other compression stages are bypassed. Every+/-line, hunk header, and blame annotation is preserved verbatim. Also protected in the MCP server path (ctx_shell). - zsh shell hook breaks command completion — After sourcing the lean-ctx shell hook, tab completion for aliased commands (
git,cargo,docker, etc.) stopped working. Added a zsh completion wrapper (_lean_ctx_comp) that delegates to the original command's completion function via_normal. Fixes #193.
Added
- Roadmap: Context Runtime research modules — 13 new core modules implementing research from information theory, graph theory, and cognitive science:
adaptive_chunking— Content-defined chunking with Rabin-Karp fingerprinting and entropy-aware split pointsattention_placement— Attention allocation scoring based on recency, frequency, and structural importancecognitive_load— Cognitive load estimation using Halstead metrics and cyclomatic complexitycyclomatic— Cyclomatic complexity analysis via control-flow graph extractiongamma_cover— Gamma cover set selection for minimal representative context subsetsgraph_features— Property graph feature extraction (betweenness, clustering coefficient, community bridge detection)information_bottleneck— Information bottleneck compression with iterative Blahut-Arimotomdl_selector— Minimum Description Length model selection for compression strategymemory_consolidation— Memory consolidation with exponential decay and importance-weighted retentionprogressive_compression— Multi-level progressive compression with quality gatessplade_retrieval— Sparse Lexical and Expansion retrieval for context-aware searchstructural_diff— AST-level structural diff for semantic change detectionstructural_tokenizer— Language-aware tokenization using tree-sitter AST for 18 languages
- Louvain community detection O(m) — Rewrote
community.rsfrom O(n²) adjacency scan to edge-list-based Louvain with modularity optimization, supporting weighted edges and hierarchical communities. - Enhanced PageRank — Damped PageRank with configurable alpha, convergence detection, and seed biasing for context-aware node ranking.
- SPLADE-enhanced BM25 — BM25 index now supports sparse expansion terms for improved recall on semantically related queries.
- Config module restructured — Split monolithic
config.rsintoconfig/mod.rs,config/memory.rs,config/proxy.rs,config/serde_defaults.rsfor maintainability. shell_activationconfig option — Newshell_activationsetting inconfig.tomlwith three modes:always(default, backward-compatible),agents-only(auto-activates only in AI agent sessions like Claude Code, Cursor, Windsurf), andoff(fully manual). Controlled via config file orLEAN_CTX_SHELL_ACTIVATIONenvironment variable. Addresses feedback that lean-ctx shell hooks were too invasive for users who only need it in specific AI agent contexts..lean-ctx-idproject identity file — Projects can now declare a unique identity via a.lean-ctx-idfile in the project root. This takes highest priority in composite project hashing, solving Docker environments where multiple projects share the same mount path (e.g./workspace). Simply create a file with a unique name (e.g.echo "my-project-alpha" > .lean-ctx-id).- Identity-aware storage for all caches —
graph_index,semantic_cache,bandit, andembedding_indexnow use composite project hashes (path + identity markers) instead of path-only hashes. Includes automatic migration from legacy storage locations. Fixes cross-project context bleed in Docker environments. - Security hardening test strengthened — Dashboard token embedding no longer falls back to loopback bypass; tests now verify the stricter
valid_query-only gate.
Upgrade
lean-ctx update # recommended (auto-downloads + refreshes shell hooks)
cargo install lean-ctx # or
npm update -g lean-ctx-bin # or
brew upgrade lean-ctxNote: After upgrading via cargo/npm/brew, run
lean-ctx setupto refresh shell aliases.lean-ctx updatedoes this automatically.
Full Changelog: v3.5.16...v3.5.16