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
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,13 +25,14 @@ This document maps threats to mitigations and verification. It complements [tool
25
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` 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|
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` (`test_collect_approval_signatures_async_non_blocking`, quorum/dedup) |—|
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
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
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 |
35
+
| NFS / multi-writer JSONL corruption | High | Single-writer per workspace; `fcntl` + `atomic_write_text` on supported local FS; SQLite for Context Bus / OAuth | ADR 0008, `teaagent selftest`| Do not share `.teaagent/runs/*.jsonl` across concurrent hosts on NFS without DB migration |
0 commit comments