Release 0.11.0: security hardening + 10-issue improvement program#35
Merged
Conversation
…-deny - Replace allow-by-argv0-name + substring heuristics with shlex tokenization, quote-aware control-operator segmentation, and per-tool token deny rules; fail-closed on parse failure, redirection, command/process substitution. - Closes auto-allow bypasses: env/awk(system)/sed/find-fd-exec/interpreter -e-or-verbose/git config-branch-tag-remote/tar/zip and shell-metachar evasion.
Distinct (cwd, command) pairs no longer collide on a shared ':' separator, preventing reuse of a cached verdict for a different command.
A literal-colon deny/allow rule now matches a literal-colon command instead of silently failing on the asymmetric pattern-only normalization.
Introduces config::codex_trust (ProjectTrust + read_project_trust) as the canonical reader so clx and clx-hook can drop their duplicate copies. Preserves global-only read, canonical-path lookup, and no repo self-declared trust.
- Convert config/trust.rs from anyhow to a typed TrustError so callers can match malformed / unsupported-version / IO failures. - Remove unused Error::PolicyViolation and provider-named Error::Ollama variants.
Record/consult a file-based primary-failure marker so a recent primary outage seen by a prior one-shot hook process short-circuits to the fallback instead of re-hitting the dead primary every invocation.
Credential get/list now bounded-retry a present-but-empty file before erroring, removing a spurious "corrupt" failure on the LLM-auth path; the write path keeps its fail-closed no-overwrite guarantee.
…azard - decay: doc now says nearest-rank (matches the code), not NIST R6. - redaction: pass-2 iterates chars instead of byte-indexing a UTF-8 string, removing a latent panic/corruption hazard; ASCII output is unchanged.
RecallEngine::query returns RecallQueryResult { hits, degraded }; stage errors
set degraded instead of silently folding to empty. MCP surfaces degraded-empty
as "temporarily unavailable" and the hook never injects an outage string.
read_bounded_line accumulates bytes to the delimiter and decodes once, instead of per-chunk lossy decoding that corrupted multibyte chars at buffer boundaries.
…_input - Remove the unused HookDeps (built, passed as _deps, dropped while handlers re-loaded); handlers self-resolve config/storage. This also stops the prior fail-open early-return when startup storage-open failed: command validation now always runs (only audit/cache writes degrade) when the DB is unavailable. - Move the production-dead parse_input wrapper under #[cfg(test)].
…function - Use clx_core::config::codex_trust instead of the local duplicate reader. - Remove the unreachable legacy trust-token allow block. - Extract handle_pre_tool_use into phase helpers (fileedit guard, L0, L1 escalation, audits); behavior and fail-closed arm ordering preserved.
…asses Codex verification round: is_redirection_token now catches N-prefixed and &> redirection forms, and the sed flag heuristic flags e/w inside combined flag runs such as s///ep.
Second Codex verification round: sed danger detection now parses each
substitution to its real flag region (any flag order, any delimiter), closing
s///pe and s#...#e; redirection detection also strips a Bash named-fd prefix
so {fd}>file is rejected.
…ction guard - Add hidden builtin PolicyRuleType::Graylist; evaluate denies per-segment (any), allows only when every non-cd segment is whitelisted (no any-segment bypass). - Reclassify over-broad builtins (backtick, process-subst, default-expansion, source/eval/exec) to ask; narrow python -c to destructive calls. - Add L0 deny rules for redirection/tee/cp/mv/dd into protected config dirs and narrow the agent-config FileEdit rule to settings/hooks. - Extend is_read_only_command with cd/sort/uniq/cut/column (guarded).
Row-scan deletes learned_rules entries that trip the shared secret or well-formed detectors (logged redacted); idempotent; SCHEMA_VERSION 8->9.
…decision docs - CapabilityRoute.dimension + effective-dimension resolver (route > registry > legacy); Azure backend sends the configured dimension instead of a literal. - Doc-only: default_decision applies to L1 runtime failures; disabling L1 forces ask.
…ed denials - Strip leading env-assignments; reject raw secret/compound commands and malformed patterns before writing a learned rule (reuses clx-core detectors). - DecisionSource::Automated denials never learn; user rejections still do.
…ooks Narrow the canonical FileEdit protected-dir guard so non-sensitive agent-config paths (memory files) are allowed; settings.json/settings.local.json/hooks and the other config dirs stay denied. Pass automated source on the L1-deny path.
…en for Codex Truthy CLAUDECODE takes precedence over the turn_id envelope sniff (after the explicit CLX_HOOK_HOST override), so 'ask' no longer hard-blocks under Claude Code.
…e reset Export/import a versioned JSON envelope (import re-validates via the shared secret/well-formed gates, accepting wildcards); reset --learned-only is the default and preserves explicit global allows, --all drops everything.
… allow Codex verification round: strictly parse the imported rule_type so a "graylist" or bogus value is rejected, never coerced into an allow rule (fail-open).
…get writes Codex verification round: narrow the dot-claude Bash-redirection deny rules to settings.json/settings.local.json/hooks (mirroring the FileEdit guard) so redirecting into agent memory files is no longer blocked.
Bump workspace version 0.10.1 -> 0.11.0 and add the 0.11.0 changelog entry (security fix campaign + 10-issue improvement program; schema v8->v9).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Releases v0.11.0 (bumped from 0.10.1). 38 commits: a security fix campaign followed by the 10-issue source-improvement program from
docs/CLX_SOURCE_IMPROVEMENT_PLAN.md. Merging this PR triggersrelease-plz→ tagv0.11.0→release.yml(arm64 macOS build + GitHub Release + Homebrew).Highlights
Security
awk system(),find/fdexec, interpreter-e/verbose,git config/branch,tar/zip,sedexec flags, arbitrary-fd redirection, metachar evasion).tee/cp/mv/ddwrites into protected config dirs.rules importvalidation.Added
clx config get/set;clx rules export/import+ scope-awarereset.Fixed
clx healthwarns on unresolved routes; agent memory files writable while settings/hooks protected; MCP UTF-8-safe line reads; recall degraded signal; Azure probe timeout; cross-process fallback cooldown; transactional v1 migration.Full details in
CHANGELOG.md(0.11.0).Verification
cargo test --workspace: 2141 passed / 2 failed — the 2 failures are pre-existing host-routing e2e tests (sniff_*, fail at basece6814e), unrelated to this work.cargo clippy --workspace --all-targets -- -D warnings: clean.cargo fmt --check: clean.gitleaks detect: no leaks.Notes
sniff_*e2e failures should be triaged separately.