Skip to content

fix: OCP code-audit P1+P2 hardening (crash bugs + multi-tenant gates)#106

Merged
dtzp555-max merged 4 commits into
mainfrom
fix/audit-p1-p2
May 31, 2026
Merged

fix: OCP code-audit P1+P2 hardening (crash bugs + multi-tenant gates)#106
dtzp555-max merged 4 commits into
mainfrom
fix/audit-p1-p2

Conversation

@dtzp555-max

Copy link
Copy Markdown
Owner

Fixes the 3 P1 + 5 P2 findings from the multi-agent OCP code audit (23/24 confirmed after adversarial verification). Independently reviewed: APPROVE-WITH-MINOR (default-path-sacred verified by diffing buildCliArgs + the isAdmin move against the parent; 2 minor findings folded).

P1 — availability / correctness (the reason to patch before any durable deploy)

  • P1-1 proc.stdin had no 'error' listener → an EPIPE from a fast-failing child (auth error, bad model, big prompt) crashed the single-process daemon. Now swallowed+logged.
  • P1-2 un-awaited async handler + no unhandledRejection/uncaughtException/clientError nets + unguarded body-read loops → a normal client aborting mid-upload crashed the daemon. Added process safety nets + try/catch on all 4 body loops.
  • P1-3 TUI reader treated stop_reason:"tool_use" as turn-complete → silently truncated any TUI turn that used a tool. Now only turn_duration is terminal.

P2 — security gates / cache integrity

  • P2-1 default stream-json path: in AUTH_MODE=multi, force --disallowedTools (Bash/Read/Write/Edit/…) so a guest prompt can't drive operator-FS tools. Single-user (none/shared) path unchanged.
  • P2-2 /sessions (DELETE), /settings (PATCH), /logs, /usage, /status were dispatched before the isAdmin check → now admin-gated.
  • P2-3 streaming path cached an is_error response as success → cache poisoning. Now an errored flag routes it to recordModelError, no cache write.
  • P2-4 TUI fail-loud guard extended: also refuses boot on none+0.0.0.0 (unless OCP_TUI_ALLOW_LAN=1) and + PROXY_ANONYMOUS_KEY.
  • P2-5 TUI send-keys paste now uses -l (literal) → a prompt equal to a tmux key token (e.g. C-c) is typed, not interpreted.

Invariants

Default single-user path (AUTH_MODE=none, no TUI) is behavior-identical (buildCliArgs diff confirmed byte-for-byte; the new code is no-op on the happy path). node test-features.mjs136/0.

Follow-up (not blocking)

  • Live-verify the P2-1 --disallowedTools denial on PI231 before any production multi deployment.
  • P3 findings (14) tracked separately for a cleanup pass.

🤖 Generated with Claude Code

dtzp555 and others added 4 commits May 31, 2026 13:07
In spawnClaudeProcess, attach an error listener on proc.stdin BEFORE
the write/end calls so an EPIPE (child closed stdin mid-write) is
swallowed and logged rather than thrown as an unhandled exception.

The existing proc.on("error") listener is on the ChildProcess object,
NOT on the stdin Writable — it does not catch stdin write errors.

Hardening per OCP code audit; entry-surface contract unchanged for
single-user default path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n is terminal

In interactive TUI mode, stop_reason=tool_use does NOT mean the turn is
complete. Claude handles the tool call internally and continues generating —
the transcript advances to another assistant entry. Treating tool_use as
terminal truncated tool-using turns mid-flight.

Only {type:"system", subtype:"turn_duration"} is the authoritative
completion marker (claude CLI v2.1.157+ interactive session transcript).

Updated two unit tests that previously asserted tool_use → true; they now
assert false (the correct behaviour). The real-fixture terminal detection
test is unaffected because the fixture uses turn_duration.

Hardening per OCP code audit; TUI path behaviour fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A prompt that equals a tmux key token (e.g. "C-c", "Escape") would be
interpreted as that key binding rather than typed as literal text.

The -l flag forces literal character-by-character input. The separate
Enter key event afterward deliberately omits -l so tmux sends a real
carriage-return keypress to submit the prompt line.

Authority: tmux send-keys(1) § -l flag. Hardening per OCP code audit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ew fast-follow)

Folds the 2 minor findings from the independent review of the audit fixes:
- String(parsed.error) before .slice/message in callClaude + callClaudeStreaming
  (defensive: claude could emit a non-string result/error_message).
- correct the readTuiTranscript comment that still listed tool_use as terminal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dtzp555-max dtzp555-max merged commit 05a984d into main May 31, 2026
5 checks passed
@dtzp555-max dtzp555-max deleted the fix/audit-p1-p2 branch May 31, 2026 03:17
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.

2 participants