You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
L12: serialize TTY prompts process-wide and share friction accounting (#84)
- internal/danger/approver.go: add a process-wide mutex (ttyPromptMu) that
serializes all TTY approval prompts; move the approval log that drives
friction mode to a process-wide map so repeated approvals across tool
instances correctly engage high-friction mode. Reset the global log in
test mode on each NewTTYApprover so tests stay isolated.
- internal/danger/whitebox_coverage_test.go: update record-approval test
for the global log.
- cmd/odek/parallel_shell_danger_test.go: reset friction state before the
trust-cache test.
- docs/SECURITY.md + AGENTS.md: document L12 mitigation.
-**Telegram log file permissions** (`internal/telegram/log.go`) — Telegram log files are created with `0600`, and `os.Chmod` hardens existing files. Chat IDs and task snippets are no longer world-readable by default.
183
183
-**Telegram chat-scoped sessions and plans** (`internal/telegram/session.go`, `internal/telegram/plan.go`, `cmd/odek/telegram.go`) — `/sessions`, `/resume`, `/prune`, `/plans`, `/plan_view`, `/plan_delete`, and `/plan_resume` are scoped to the requesting chat. Sessions are filtered by the `tg-<chatID>` prefix, `ResumeSession` rejects cross-chat IDs, and plans live under `~/.odek/plans/chat<chatID>/` so one chat cannot list, read, delete, or resume another chat's sessions/plans.
184
184
-**Telegram clarify callback binding** (`cmd/odek/telegram.go`, `internal/telegram/handler.go`) — each `clarify` prompt now uses a random request ID in its inline-keyboard callback data (`clarify:<reqID>:yes/no`). The handler validates the request ID and binds the answer to the originating user, so a group member or stale keyboard cannot answer someone else's clarify prompt. `Handler.OnCallbackQuery` now receives the `userID` for consistent callback binding.
185
+
-**Process-wide TTY prompt serialization + friction accounting** (`internal/danger/approver.go`) — all CLI TTY approval prompts are serialized by a process-wide mutex so concurrent tool calls cannot interleave prompts on `/dev/tty`; the approval log that drives friction mode is shared across TTYApprover instances, so the high-friction "type `approve`" path engages after repeated approvals regardless of which tool instance recorded them.
185
186
-**odek self-invocation gate** (`internal/danger/classifier.go`) — any shell stage whose program basename is `odek` is classified as `system_write`. This prevents a prompt-injected agent from reaching the human-gated trust mutations (`odek memory promote`, `odek memory extended confirm`, `odek skill promote --force`) through the shell tool and flipping its own taint gates.
186
187
-**MCP inputSchema hardening** (`cmd/odek/mcp_approval.go`) — every string in an MCP tool's `inputSchema` is recursively guard-scanned for injection patterns; schemas larger than 256 KiB are rejected; the interactive approval prompt shows a SHA-256 hash and byte size of the schema so operators can detect changes.
187
188
-**MCP tool batch classification** (`internal/loop/loop.go`) — MCP tools (`<server>__<tool>`) are classified as `unknown` by `classifyToolCall`, so the batch approval gate shows them and untrusted sub-agents force them to `deny`.
Copy file name to clipboardExpand all lines: docs/SECURITY.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -673,6 +673,12 @@ The Telegram bot's `clarify` tool sent inline keyboard buttons with literal call
673
673
674
674
Each clarify prompt now generates a random request ID (embedded in callback data as `clarify:<reqID>:yes/no`). The handler validates the request ID, rejects callbacks from a different user than the one who triggered the prompt, and ignores callbacks for expired or already-answered prompts. The `Handler.OnCallbackQuery` signature now receives the originating `userID` so other callback handlers can apply the same binding.
675
675
676
+
### 39o. Process-wide TTY prompt serialization and friction accounting
677
+
678
+
In CLI mode, concurrent tool calls (for example, `parallel_shell`) each opened `/dev/tty` with their own reader and printed prompts simultaneously. A user could approve a command they never saw, and the per-instance approval log meant friction mode never engaged across prompts.
679
+
680
+
`TTYApprover` now serializes all TTY prompts with a process-wide mutex, and the approval log that drives friction mode is shared across all instances. Concurrent prompts queue behind the active prompt, and repeated approvals of the same class within the friction window correctly trigger the high-friction "type `approve`" path.
681
+
676
682
### 40. `/api/resources` result limit cap
677
683
678
684
The `/api/resources?q=...&limit=N` autocomplete endpoint previously accepted any positive `limit` value. It is now capped to 100 results both in the HTTP handler and in `Registry.Search`. This prevents a prompt-injected or attacker-forged request from forcing an unbounded directory walk and returning a multi-megabyte JSON response.
0 commit comments