Skip to content

fix: deep review findings — security, engine, storage, tools - #195

Merged
Patel230 merged 16 commits into
mainfrom
fix/deep-review-findings
Aug 14, 2026
Merged

fix: deep review findings — security, engine, storage, tools#195
Patel230 merged 16 commits into
mainfrom
fix/deep-review-findings

Conversation

@Patel230

Copy link
Copy Markdown
Contributor

Summary

Fixes findings from the deep code review across security, engine, storage, tool, and CLI subsystems. All changes verified twice: build ✓, vet ✓, lint 0 ✓, full test suite ✓.

Security

  • C2: Container egress now restricted via NetworkProxy (default allowlist: npm/PyPI/GitHub/Go/crates.io/Docker Hub); container reaches proxy via host.docker.internal. Opt out with HAWK_DISABLE_EGRESS_PROXY=1.
  • C3: Guardian response parser now prefers the JSON object carrying the allowed key, skipping injected spoofed fragments.
  • H7: CORS no longer reflects arbitrary origins with credentials — wildcard sends * without creds.
  • H8: Credential-bearing path segments (e.g. Telegram /bot<TOKEN>) redacted in request logs.
  • H10: Auto-allow prefix matching now bounded — approving git status no longer auto-approves git status; rm -rf /.

Engine

  • H3: Extracted buildTurnOptions(turnContext) from the 877-line agentLoop.
  • H4: Activity nudge injected ephemerally (was persisting and accumulating every turn).
  • H11/H12: Removed dead timeout context in auto-remember goroutine; added emit() helper with ctx.Done() guard on all post-stream channel sends.
  • M1: compactModel now lets free/local models (price 0) win for summarization.
  • M2: Spec constitution cached keyed on path + mtime (was re-read from disk every turn).
  • M8: SemanticCompress recent-detection now uses each member's original index (was matching by content equality, wrong on repeated text).

Storage

  • H13: Deleted dead SQLiteStore + GainTracker and their tests (2063 lines, zero production callers).
  • M7: Snapshot/checkpoint index writes now atomic (safewrite temp+rename).
  • H14: Renamed internal/engine/sessioninternal/engine/compression (removed naming collision with internal/session).
  • M6: Documented BatchedWAL's durability window.

Tools

  • H5: Registry.Execute releases the read lock before tool execution (was serializing parallel tools).
  • H6: Tool errors now preserve partial output before the error prefix.
  • M10: Introduced typed ToolSchema + SchemaProvider interface; ValidateToolInput now checks types/enums when provided. Bash and FileRead converted as reference implementations.
  • M9: Corrected Refactorer doc comment (regex-based, not AST-based) with scope limitations noted.

CLI

  • H2: Removed dead slashSel mutation inside by-value View().
  • M11/M12: Added drift-prevention tests (no tool overlap between essential/optional lists; package subcommand registry populated).

Session

  • M15: CoherenceTracker.GetState now deep-copies slices/pointers (was sharing internal arrays with callers).

Lint

  • Enabled errorlint; fixed 19 production files (errors.As for type assertions, %w for error wrapping).

Co-Authored-By: Claude noreply@anthropic.com

Pulls provider autodetection and model ID canonicalization fixes
- H5: drop RLock in Registry.Execute before tool execution so parallel
  tools within a turn are no longer serialized behind a read lock.
- H6: preserve partial tool output before the error prefix so the LLM
  sees what a tool produced before it failed.
- M1: let free/local models (price 0) win as the compaction model.
- M14: widen isSmallTalkPrompt via conservative phrase + filler matching
  (guarded so a trailing request clause like "hi, inspect this" stays false).
- C5: make SnowballDetector.IsSnowballing an honest growth-rate check; the
  progress-per-token clause was provably redundant with a constant signal.
- H2: remove dead slashSel mutation inside by-value View() (clamped in Update).
…nel sends

- H4: move the activity-nudge injection from persisted (AppendSystemContext,
  every-turn leak) to ephemeral opts.System so it never accumulates.
- M2: cache the spec constitution.md read keyed on path + mtime, so unchanged
  files are not re-read from disk every turn.
- H11: remove the dead timeout context in the auto-remember goroutine
  (Remember does not accept a context); document it as best-effort fire-and-forget.
- H12: add an emit() helper that selects on ctx.Done() and use it for all
  post-stream bare channel sends, so an early-exit consumer can't leak the
  agentLoop goroutine.
Pull the per-turn ChatOptions assembly (system-prompt tiering, ephemeral
injections for beliefs/memory nudge/smart skills/spec stage/work mode, and
promoted tools) into a dedicated buildTurnOptions(turnContext) helper. Pure
behavior-preserving extraction: agentLoop now hands a turnContext to the
helper and uses the returned opts, shrinking the loop and giving the
prompt-assembly logic a single, testable home.
Fix the NetworkProxy request routing: ServeMux pattern '/' does not match
authority-form CONNECT targets (e.g. 'CONNECT host:port'), so HTTPS clients
fell through to 404. Implement ServeHTTP directly on the proxy so CONNECT
tunneling and plain-HTTP forwarding both route correctly.

Bind the egress proxy with tcp4 when host is 0.0.0.0 so containers reach it
via IPv4 host.docker.internal (on macOS/Orbstack, 'tcp'+'0.0.0.0' yields an
IPv6 [::] socket that drops IPv4 connections).

Make docker-CLI discovery robust to test/daemon subprocess PATH differences
by also checking /Users/$USER/.orbstack/bin/docker.

Add an end-to-end egressproxy-tagged integration test that verifies an
allowed domain tunnels through (real HTTPS to github.com) while a blocked
domain is rejected (403).

Bump go.mod and go.work to go1.26.6, which resolves the stdlib
vulnerabilities (GO-2026-6218, GO-2026-6091, GO-2026-6090) flagged by
govulncheck.

EOF
)
CI runs on Go 1.26.5 with GOTOOLCHAIN=local, so requiring 1.26.6 broke
every check (vet, test, build). Keep all module files on 1.26.5; the
stdlib vulns are pre-existing and not introduced by these changes.

EOF
)
Go 1.26.6 patches stdlib vulnerabilities (GO-2026-6218, GO-2026-6091,
GO-2026-6090) that govulncheck flags as reachable from pre-existing code.
Bump go.mod, go.work, and every CI workflow's go-version pin so setup-go
installs 1.26.6 — this satisfies go.work, unblocks the build, and clears
govulncheck.

EOF
)
The parent branch (feat/sync-eyrie-add-providers) moved the eyrie submodule
to commit 7ec579abfaa9 but did not update go.mod's require version, which
broke the submodule/module release parity check. Update the pseudo-version
to resolve to the pinned commit.

EOF
)
go work sync updates go.sum to reflect the new eyrie pseudo-version.

EOF
)
The Dockerfile, Dockerfile.daemon, Makefile, and setup-deps action all
generate a go.work with a hardcoded Go version. Bump each from 1.26.5 to
1.26.6 so they match go.mod/go.work and the Docker/CI build does not reject
the version mismatch.

EOF
)
Align the Docker build image with go.mod/go.work (1.26.6) so the build
does not reject the toolchain version inside the container
(GOTOOLCHAIN=local prevents auto-download). Pinned by digest for
supply-chain hardening.

EOF
)
@Patel230
Patel230 merged commit a818ea5 into main Aug 14, 2026
26 checks passed
@Patel230
Patel230 deleted the fix/deep-review-findings branch August 14, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant