Fix major correctness, security, and data-loss issues in core + agentic crates#85
Merged
Conversation
…ic crates Reviewed hi-agent, hi-tools, hi-ai, hi-cli, hi-tui, and hi-lsp and fixed the confirmed major issues (mlx/cuda excluded). All tests pass and clippy is clean under -D warnings; regression tests added for the highest-impact fixes. hi-tools (security): - Reject IPv4-mapped IPv6 (`[::ffff:169.254.169.254]`) in the SSRF blocklist. - Resolve symlinks in every existing ancestor so a workspace symlink through a not-yet-existing dir can't escape the path guard. - Block `rm -r` of home/root/system paths even without `-f`. - Cap web_fetch body reads (8 MiB) instead of buffering the whole response. hi-agent (correctness / data loss): - Read-only turns no longer treat the 12k soft elision threshold as the real context window, which durably discarded whole sessions; destructive drops now use the real model window. - Clamp the persist cursor so nudge-stripping can't panic persist() with an out-of-bounds slice. - Enforce ReadOnly/ChatOnly tool_mode at execution time so text-promoted tool calls can't bypass it (explore subagents included). - Don't abort the explore subagent before its first model call on common verbs. - PID-scope the memory temp file so concurrent writers can't tear it. hi-cli: - Skip the first-run wizard (which blind-overwrites config) when profiles exist. - Don't apply a delegate child's partial diff on a non-zero exit. - Require a name for `/provider remove`; track active profile on `/provider` switch. - Keep 0600 perms in the api-key migration and don't materialize env secrets to disk. - Exclude fleet/loop sessions from `hi -c`. hi-ai / hi-lsp / hi-tui: - Match LSP responses only on method-less messages (request-id collision). - Bound the OpenAI post-finish usage grace with a total deadline (was per-chunk). - Keep a finished Anthropic answer on an unclean mid-stream close instead of re-billing. - Preserve cache tokens / reference-call usage in fallback and moa; saturating token math. - Reclaim the loop single-firer lock atomically to avoid two holders double-firing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adversarially audited the pass-1 fixes and ran deeper reviewers over the scheduler, side-calls, hi-tui loops/app, and hi-tools plumbing. Fixed the confirmed issues (mlx/cuda excluded); all tests pass, clippy clean under -D warnings. Regressions introduced by pass-1 fixes: - fallback.rs: the usage merge dropped the winner's context_occupancy / input_includes_cache (Usage::add doesn't carry them), mis-counting cache tokens and tripping early auto-compaction. Preserve the winner's scalars. - guard.rs: dropping the -f requirement over-blocked routine deep cleanup (`rm -r ~/.cache/x`). Tier it: top-level roots (`rm -r ~`, `/etc`) block on -r alone; deeper paths only with -f (restoring prior protection). New findings: - checkpoint.rs: /undo silently skipped non-ASCII filenames (git octal-quotes --name-status paths); use NUL-delimited -z output. +test. - hi-agent side-call errors (skeptic/curate/memory/plan/finalize/summarize) clobbered the main context_used gauge via add_error_usage, disabling the next auto-compaction. Add add_side_error_usage that leaves the gauge alone. - tool_deps didn't serialize a write after an earlier read of the same path, so `[read X, write X]` ran concurrently and the read could see a torn file. +test. - hi-tui event_log grew unbounded (one entry per streamed chunk, never trimmed); cap it and clear it on /clear. - loops: firings was bumped at spawn, so a failed first firing left the loop reporting "nothing new" against a baseline it never established. Roll back on error. - best-of/delegate/fleet children re-resolved config and a default-profile literal api_key shadowed the parent's key (silent auth failure with --profile/--api-key). Pass HI_FORCE_API_KEY (env, not argv) so the parent's key wins. - provider_form: /provider edit of an Ollama profile opened focused on the hidden API-key field; skip_hidden() in the constructor. Noted but not changed (low-severity / out of scope): background.rs kill nanosecond-window race, loop lock 3-process race, per-profile migration persist, child config-flag forwarding, and the hi-tui O(transcript)-per-token render cost. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The blocking CI job (`cargo fmt --all --check`) rejected the hand-formatted multi-line boolean/method-chain expressions from the two fix commits. No logic change — pure `cargo fmt` normalization. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Two-pass review of the core and agentic-coding crates (
hi-agent,hi-tools,hi-ai,hi-cli,hi-tui,hi-lsp); thehi-mlx/hi-cudalocal-inference crates were out of scope. Every finding was verified against the code before fixing. All core-crate tests pass and clippy is clean under-D warnings; regression tests were added for the highest-impact fixes.Pass 1 — initial fixes (
d895a5b)hi-tools (security)
[::ffff:169.254.169.254]) in the SSRF blocklist.rm -rof home/root/system paths even without-f.web_fetchbody reads (8 MiB) instead of buffering the whole response.hi-agent (correctness / data loss)
persist()with an out-of-bounds slice.tool_modeat execution time so text-promoted tool calls can't bypass it (explore subagents included).hi-cli
/provider remove; track active profile on/providerswitch.hi -c.hi-ai / hi-lsp / hi-tui
Pass 2 — adversarial audit of pass 1 + deeper review (
1a76c5e)Regressions introduced by pass 1 (caught by an adversarial re-review)
fallback.rs: the usage merge dropped the winner'scontext_occupancy/input_includes_cache, mis-counting cache tokens and tripping early auto-compaction — now preserves the winner's scalars.guard.rs: dropping the-frequirement over-blocked routine deep cleanup (rm -r ~/.cache/x). Tiered it — top-level roots (rm -r ~,/etc) block on-ralone; deeper paths only with-f.New findings
checkpoint.rs:/undosilently skipped non-ASCII filenames (git octal-quotes--name-statuspaths) — switched to NUL-delimited-zoutput. Restores the "anything is undoable" guarantee.context_usedgauge, disabling the next auto-compaction — addedadd_side_error_usage.tool_depsdidn't serialize a write after an earlier read of the same path ([read X, write X]could read a torn file).event_loggrew unbounded (one entry per streamed chunk, never trimmed) — capped and cleared on/clear.firingsbumped at spawn, so a failed first firing reported "nothing new" against a baseline it never established — roll back on error.api_keyshadowed the parent's key (silent auth failure) — passHI_FORCE_API_KEY(env, not argv).provider_form:/provider editof an Ollama profile opened focused on the hidden API-key field.Deliberately deferred (low-severity or out of scope)
--compat/--tool-mode), and the hi-tui O(transcript)-per-token render cost — all worth follow-ups.Testing
cargo testandcargo clippy --all-targets -- -D warningspass acrosshi-agent,hi-ai,hi-tools,hi(hi-cli),hi-tui,hi-lsp.🤖 Generated with Claude Code