Revision History
| Date | Author | Changes |
|---|---|---|
| 2026-03-10 | langster-threat-model (automated) | Initial threat model |
| 2026-03-27 | langster-threat-model (automated) | Deep expansion: added C11-C16 (server subprocess, RemoteAgent, LocalContextMiddleware, async subagent config, custom subagent loader); added TB8-TB10 (CLI/server IPC, LocalContext/host env, RemoteAgent/dev server); added DF18-DF22; added T6 (unauthenticated dev server), T7 (Makefile injection), T8 (subagent body injection); updated T5 (upstream msgpack fix confirmed); added data classification; added Investigated and Dismissed section; updated architecture diagram to reflect server-subprocess model |
| 2026-03-28 | langster-threat-model (automated) | Deep validation pass: added C17 (Model Config Loader with class_path), TB11 (Config→Code Execution); added DC5 (offloaded conversation history); added DF23-DF25 (class_path flow, MCP env dict flow, offload flow); added T9 (class_path arbitrary code execution), T10 (MCP env dict unfiltered); added D3 (SSRF dismissed — HITL is intended control), D4 (offload path injection dismissed — UUID7); removed Status column and Mitigations/Residual Risk fields from all threats (open source visibility compliance — mitigation status must not appear in public threat models); updated T6 validation from Likely to Verified (port is deterministic at 2024 default, discoverable via /proc); updated external context (no published advisories found); updated architecture diagram |
| 2026-06-25 | manual update | Added T12 (project .env injects shell interpreter startup hooks) under TB11; extended the TB11 boundary controls and details with the dotenv shell-startup-hook denylist (BASH_ENV, ENV); clarified the .env out-of-scope row to separate ordinary config discovery from the in-scope code-execution implication |
| 2026-06-25 | manual update | Updated T6 and TB10 to reflect the dev server binding an OS-assigned ephemeral port by default (server._EPHEMERAL_PORT) instead of squatting the well-known langgraph dev port 2024; noted unpredictable-port-across-runs as added defense-in-depth in the port-discovery dismissal row |
| 2026-07-08 | manual update | Removed the SHA-256 config fingerprint trust store (mcp_trust.py, ~/.deepagents/.state/mcp_trust.json, DC4). Project MCP trust is now the interactive approval prompt (allow-for-session / always-allow scoped to project root + server-definition fingerprint / deny), the --trust-project-mcp run flag, the [mcp].enabled_project_server_approvals and [mcp].disabled_project_servers lists, and the process-wide DEEPAGENTS_CODE_DANGEROUSLY_ENABLE_PROJECT_MCP_SERVERS name-based escape hatch. The legacy flat [mcp].enabled_project_servers key is ignored. Persisted approvals bind to a server definition's fingerprint rather than a whole-config fingerprint. Updated C5, TB4, T10, the configuration input-coverage row, and the malicious-MCP-server dismissal accordingly |
| 2026-07-21 | manual update | Clarified TB4 after process-wide MCP names and scoped remembered approvals changed from replacement semantics to independent grants. An empty process-wide allowlist no longer suppresses remembered approvals; disabled-server precedence is unchanged. |
| 2026-07-22 | manual update | Added T13 (first-token shell allow-list bypass via allow-listed interpreters/wrappers) under TB2, distinguishing it from T2's --shell-allow-list all sentinel; cross-referenced it from T2 and extended the "LLM output" input-coverage gap to note that allow-list matching only inspects the command's first token |
| 2026-07-24 | manual update | Corrected the out-of-scope hooks row: Hooks v2 defaults are 600s (30s for UserPromptSubmit), not a global 5-second timeout; loading is hooks.loading.load_hooks_config; project hooks require workspace trust or --trust-project-hooks |
| 2026-07-28 | manual update | Extended the out-of-scope hooks row for plugin-contributed hooks: enabled plugins may supply hooks/hooks.json, gated by install plus enablement rather than workspace trust, with each handler's environment overlaid only by its own plugin path variables |
| 2026-08-03 | manual update | Added T14 (a weaker Auto classifier model weakens action review) under TB2, covering the selectable classifier (--auto-classifier-model, DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL, [models].auto_classifier, /auto model), its restriction to trusted config surfaces via config._PROJECT_DOTENV_DENIED_ENV_KEYS, and its fail-closed construction behavior (deny, then latch to human approval; never fall back to the main model). Extended the "LLM output" and "Configuration" input-coverage rows with T14 |
| 2026-08-04 | manual update | Extended T14 for the configurable Auto classifier review deadline (DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT, [models].auto_classifier_timeout): bounded by config_manifest.resolve_auto_classifier_timeout between a floor and ceiling so the deadline cannot be removed, denied from a project .env via config._PROJECT_DOTENV_DENIED_ENV_KEYS, and fail-closed on expiry |
| 2026-08-11 | langster-threat-model (automated) | Added C19, TB12, and DF28/DF29 for persisted goal/rubric state injected into primary-model context after removal of the goal/rubric read tools. Updated DC2 and input-source coverage; added T15 (stored prompt injection), T16 (automatic disclosure of file-loaded criteria), and T17 (context-budget pressure), with provider-handling and trust-contract gaps recorded as Open Questions. |
| 2026-08-11 | langster-threat-model (automated) | Corrected TB12, DF28/DF29, and T17 to document the enforced raw-character limits and the narrower residual risk from post-escape expansion and provider-specific byte/token budgets. |
| 2026-08-17 | langster-threat-model (diff) | Added C18, a server-owned custom HTTP boundary, and updated the architecture, DC5, TB2, TB10, DF25-DF27, T6, and input coverage. The route owns checkpoint hydration, shared compaction/hooks/backend selection, state-only persistence typed to permitted channels, and cost rollback; the client sends no graph or checkpoint state. Recorded that PreToolUse ask is fail-closed (converted to a deny) on this path because the operation transport carries no HITL channel; no new threat was identified. |
| 2026-08-17 | manual update | Noted that the goal-state character budget is re-validated when a one-shot /rubric next is consumed, not only when it is set: the goal state it is measured against is mutable between those points (/goal amend, an update_goal blocker note), so a set-time-only check could still degrade the notice and silently disable the promised grade. The degraded notice now also reports Goal status: unavailable rather than leaving a live status beside Goal actionable: no. |
| 2026-08-17 | manual update | Extended T14 for ask_user question text as a classifier injection source: the receipt attests display and answer, not content, so a question claiming prior or blanket authorization is untrusted content; recorded the _CLASSIFIER_POLICY clauses that keep a paired question to an action/target description matched against canonical arguments. Narrowed the T14 "deterministic allow/deny" guard wording, which overstated the deny side: deterministic denies do not cover the Deny categories, and an affirmative classifier allow is not re-checked downstream |
| 2026-08-19 | manual update | Recorded that a superseded goal-state notice is replaced in place rather than removed from a model request, because the summarizer derives its next cutoff from that list and persists it against the unfiltered checkpoint; and that a combined objective-plus-criteria overflow now ends the criteria turn with its character limit instead of retrying blind to the recursion limit. Noted that an unrecognized persisted goal status degrades to paused in the notice, so a corrupt or forward-version checkpoint cannot present itself to the model as a goal to work toward. Dropped the stale generated-commit pin and bounded T16's disclosure to the enforced rubric limit |
| 2026-08-21 | manual update | Clarified that the dotenv execution-hook denylist (config._DOTENV_DENIED_ENV_KEYS) is a best-effort enumeration of known code-execution consumers, not a closed set: TB11's inside-detail and T12's description now state this explicitly, and the Configuration input-coverage gap was reworded from the stale "project .env can set shell startup-hook vars" (denylisted since #4288) to the actual residual — execution-hook keys consumed by not-yet-enumerated tools still reach subprocesses |
| 2026-08-24 | langster-threat-model (diff) | Removed the client-seeded /offload fallback. /offload is now available only through C18 on built-in servers; local in-process and ACP agents do not support it, and custom or older servers without the route fail at the HTTP boundary. Updated DC5, TB2, TB10, and T6 to remove the client self-approval and synthetic-message attack surface. The server route, hook behavior, archive guard, and state-only persistence controls are unchanged; no new threat was identified. |
| 2026-08-24 | manual update | The C18 boundary now strips endpoint/proxy/transport keys (base_url, openai_proxy, http_client, and similar) from client-supplied model_params before they reach config.create_model (offload_api._strip_transport_model_params), closing the credential-redirection consequence of T6 for this route. Client-supplied model and behavioral params still flow through; in-process CLIContextSchema model params remain trusted and unfiltered |
| 2026-08-25 | manual update | Stopped replacing bounded superseded goal-state notices in model requests while retaining bounded same-index stand-ins for oversized legacy notices. Goal/rubric history now remains append-only for prompt-cache stability where safe, and the latest notice explicitly supersedes earlier notices. Updated T15 to record the residual risk that a model can still attend to older bounded goal text until compaction. |