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
Copy file name to clipboardExpand all lines: docs/threat-model.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,16 +22,16 @@ This document maps threats to mitigations and verification. It complements [tool
22
22
| Provider response schema drift | Low | JSON schema for model decisions |`test_live_provider_conformance_flow.py`| Provider-specific quirks remain |
23
23
| Unbounded run cost | Medium |`RunBudget`; iteration/tool/cost caps |`test_p0_harness.py`, `test_p0_slo_flow.py`| User must configure caps |
24
24
| JIT approval server unresponsive during wait | High | Async `_wait_for_approval` using `asyncio.Event` + `asyncio.wait_for`; SSE server remains responsive |`tests/test_phase6_jit_server.py`| Fixed synchronous `time.sleep` spin-lock blocking event loop |
25
-
| Context Bus SQLite lock contention / transaction leaks | Medium | Per-thread SQLite connections (`threading.local`); `timeout=5.0` on connect; WAL pragmas on each new connection; `_execute_with_retry` with exponential backoff (5 retries) + generation-based reconnect; explicit `conn.rollback()` on write failure; `cleanup_old_deltas` scoped to `workflow_id`|`tests/test_phase5_context_bus.py` (incl. parallel publish + workflow-scoped cleanup)| Global `_reconnect()` still closes all thread handles; see `docs/plans/remediation-roadmap.md` P2.1|
25
+
| Context Bus SQLite lock contention / transaction leaks | Medium | Per-thread SQLite connections (`threading.local`); `timeout=5.0` on connect; WAL pragmas on each new connection; `_execute_with_retry` with exponential backoff (5 retries) + generation-based reconnect (per-thread only); explicit `conn.rollback()` on write failure; `cleanup_old_deltas` scoped to `workflow_id`|`tests/test_phase5_context_bus.py` (incl. parallel publish + workflow-scoped cleanup), `tests/test_remediation_p1_p2.py`| —|
26
26
| Federated sync state corruption on crash | Medium |`atomic_write_text` + file lock on `federated_sync_state.json`; lock on pending changes |`tests/test_federated_sync.py`| File-based multi-sig quorum still experimental |
27
27
| JIT approval server race on approve/reject | Medium |`threading.Lock` on `_requests` / `_pending_events`|`tests/test_phase5_jit_approval_server.py`| Approve from thread without running event loop still drops SSE broadcast |
28
-
| Asyncio event loop starvation from synchronous P2P approval polling | High |`collect_approval_signatures`converted to `async def` with `asyncio.sleep`; `_collect_peer_signatures` dispatches via `run_coroutine_threadsafe` or `asyncio.run()`|— | Previously 5-minute synchronous `time.sleep` polling blocked event loop — now fully non-blocking|
28
+
| Asyncio event loop starvation from synchronous P2P approval polling | High |`collect_approval_signatures`is `async def` with `asyncio.sleep`; blocking I/O uses `run_in_executor`; `_collect_peer_signatures` dispatches via `run_coroutine_threadsafe` or `asyncio.run()`|`tests/test_federated_sync.py`, `tests/test_policy.py` (`MultiSigQuorumTests`) | Dedicated async poll unit test still optional|
29
29
| Shell normalization bypass via brace expansion / process substitution | High | Multi-pass `_normalize_shell_arg` now handles `{a,b}` expansion, `<()` process substitution, and non-string/non-list fallback |`tests/test_policy.py`| Catches `/pr{od,oduction}`, `<(echo /prod)`, dict-type command args |
30
30
| Protected directory bypass via alternate write tools | High |`workspace_write_*` tool pattern + `.git*` argument pattern covers all write tools and subdirectory contents |`tests/test_policy.py`, `tests/test_file_policy.py`| Previously only `workspace_write_file` was covered |
31
-
| Swarm hang / undetected thread deadlock | High |`ThreadPoolExecutor.as_completed(timeout=...)` with partial result collection; `Subagent` tracks `is_running`/`last_heartbeat`; `_heartbeat_monitor_loop` uses thread-ref liveness instead of defunct PID-based `is_process_alive`|`tests/test_swarm.py`| Previously heartbeat monitor checked parent PID (always alive) — now detects actual thread hangs |
31
+
| Swarm hang / undetected thread deadlock | High |`ThreadPoolExecutor.as_completed(timeout=...)` with partial result collection; `Subagent` tracks `is_running`/`last_heartbeat`; `_heartbeat_monitor_loop` uses thread-ref liveness instead of defunct PID-based `is_process_alive`; heartbeat hangs merged into swarm `results`|`tests/test_swarm.py`, `tests/test_remediation_p1_p2.py`| Previously heartbeat monitor checked parent PID (always alive) — now detects actual thread hangs |
32
32
| Git stash stack corruption in parallel sandboxes | Critical |`stash_save` returns actual stash reflog selector; `stash_pop` accepts specific ref |`tests/test_sandbox.py`| Previously hardcoded `stash@{0}` caused cross-agent stash confusion |
33
33
| Workflow self-healing infinite recursion | High |`_execute_step` accepts `current_attempt` parameter preserved across recursive re-execution; abort guard checks attempts against max before proceeding |`tests/test_phase5_workflow_engine.py`| Previously `self_healing_attempts` reset to 0 on new `StepExecution` — now passed through recursion chain |
34
-
| Workflow strict validation rollback never executed | High |`execute_workflow` integrates `UndoJournal` + `AuditLogger`; checks `result.requires_rollback` and calls `journal.restore()` on strict validation failure |—| Previously `requires_rollback` flag set but never consumed — now triggers full workspace undo |
34
+
| Workflow strict validation rollback never executed | High |`execute_workflow` integrates `UndoJournal` + `AuditLogger`; checks `result.requires_rollback` and calls `journal.restore()` on strict validation failure |`tests/test_remediation_p1_p2.py` (`WorkflowRollbackTests`), `tests/test_phase5_workflow_engine.py`| Previously `requires_rollback` flag set but never consumed — now triggers full workspace undo |
0 commit comments