Skip to content

fix: complete security, concurrency, architecture, and test hardening (rebased on flux) - #309

Merged
Patel230 merged 4 commits into
mainfrom
fix/hardening-v2
Sep 15, 2026
Merged

Patel230 merged 4 commits into
mainfrom
fix/hardening-v2

Conversation

@Patel230

Copy link
Copy Markdown
Contributor

Re-applies the hardening work from the closed #307 on top of the new main (flux migration #308). Four commits:

Security

  • validatePathAllowed fails closed without a ToolContext; tests attach a permissive context.
  • Delete the dead, bypassable BoundaryChecker.
  • Wrap MCP/remote tool output as untrusted external content.
  • Bound HTTP clients (stt, media); safewrite uses crypto/rand + O_EXCL; hook URL validation rejects loopback; plugin index reads capped.

Concurrency

  • Cancellable tool-event sends; cmd.Wait race fixed; lastAutoCommitHash mutex; daemon review subprocess tracking.
  • jobs cancel-status snapshot under lock; nil Done guard.
  • Bounded exec timeouts (git context, spec tools, watcher); watcher worker pool.
  • Idempotent Stop for filewatcher/cron; RunWaterfall snapshots handlers under lock.
  • AutoCommit errors logged; AssertWritable returns an error; SessionPreparations honors a context.

Architecture

  • Move IsSensitivePath/ResolvePath to internal/pathsafe; drop the config → tool edge.
  • Consolidate byte-unsafe truncate copies onto rune-safe textutil.
  • Delete dead types.ChatClient and cmd/markdown_renderer.go.

Tests / CI

  • Real bug fixes found by the new tests/fuzzer:
    • spec.extractDescription always returned empty, so every ADDED/MODIFIED requirement failed SHALL/MUST validation.
    • spec.applyRename panicked on a requirement name containing invalid UTF-8 (regexp.MustCompile on an unescaped name).
  • Spec coverage 2.4% → 24.9% + FuzzParseDeltaSpec + benchmarks.
  • Deterministic ContextDecay clock; un-skipped flaky/provider tests; removed the blanket CI -skip.
  • Golden test restores globals; make update-golden; testutil.Eventually/Never.
  • CI: per-package coverage floors, real fuzz gate, non-mutating fmt-check.

Verified locally: go vet, golangci-lint (0 issues), full go test ./..., -race on changed packages, make boundaries, coverage 68.1%, per-package floors pass.

Security:
- validatePathAllowed now fails closed without a ToolContext; tests attach a
  permissive test context.
- Delete the dead, bypassable BoundaryChecker (no production callers).
- Wrap MCP/remote tool output as untrusted external content.
- Bound HTTP clients in stt/media; safewrite uses crypto/rand + O_EXCL;
  hooks URL validation now actually rejects loopback; plugin index reads are
  capped.

Concurrency:
- jobs: snapshot cancel status under lock; guard nil Done.
- git context, spec tools, watcher: bounded exec timeouts.
- planning prompt: context-aware prompt + ctx timeout.
- watcher: bounded fireChange workers.
- filewatcher/cron: idempotent Stop (no double-close panic).
- event bus RunWaterfall: snapshot handlers under lock.
- AutoCommit errors logged; AssertWritable returns an error; SessionPreparations
  load/wait honor a context.

Architecture:
- Move IsSensitivePath/ResolvePath into internal/pathsafe; drop config->tool.
- Consolidate byte-unsafe truncate copies onto textutil (rune-safe).
- Delete dead types.ChatClient and the dead markdown_renderer.
- Fix a real bug in spec extractDescription: the requirement body excludes
  the header, so descriptions were always empty and every ADDED/MODIFIED
  requirement failed SHALL/MUST validation.
- Add spec tests (parse/validate/apply/DAG/config) lifting coverage from
  2.4% to 24.3%, plus a fuzz target and benchmarks.
- Make ContextDecay clock injectable; rewrite the timing-flaky decay tests
  deterministically.
- Un-skip TestParallelExecution, TestIntegration_FullSessionFlow, and the two
  config-apply tests; remove the blanket CI -skip.
- Golden test restores rootCmd globals; add make update-golden.
- Add testutil.Eventually/Never.
- CI: per-package coverage floors, FuzzParseDeltaSpec target, version fixture
  aligned to 0.0.1.
applyRename built a regexp with regexp.MustCompile from an unescaped
requirement name; a name containing invalid UTF-8 (or a bad pattern) panicked
the whole process. Use regexp.Compile and fall back to leaving the content
unchanged, and ReplaceAllLiteralString so $$ in the new name is not treated as
a group reference. Found by the new FuzzParseDeltaSpec target.
@Patel230
Patel230 merged commit 62b6da4 into main Sep 15, 2026
25 checks passed
@Patel230
Patel230 deleted the fix/hardening-v2 branch September 15, 2026 03:07
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