fix(python): bound Deep Agents VFS searches - #2457
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | 01224fa | Commit Preview URL | Sep 25 2026, 11:40 AM |
Two problems with the budgets as added. The session work counter only ever decreased: `_charge` subtracted every byte read and nothing but `reset()` restored it. Since no bytes are retained once an operation returns (results carry their own caps), it measured work already released, so a long-lived agent session hit a permanent "resource budget exceeded" after 100 MB of legitimate reads. The per-operation deadline, file and byte budgets are what actually bound amplification, so keep those and drop the cumulative counter. TM-DOS-106 is already assigned to zip allocation-before-check, so this threat becomes TM-DOS-113. Claude-Session: https://claude.ai/code/session_01MJBT5na4uL5yZZXwwH1FMy
6cf612f to
d50dcdf
Compare
|
Reviewed, rebased onto latest 1. The session work budget could only drain (blocking)
The effect is a long-lived agent session bricking itself after 100 MB of entirely legitimate reads: That is reachable in ordinary use — a recursive grep charges every file it walks, so a handful of searches over a moderate tree exhausts it. And the diagnostic gives the agent no way to tell a permanent session budget from a per-operation one. Fix: dropped the cumulative counter. The per-operation deadline, 10,000-file and 10 MB traversal budgets are what actually bound amplification, and they are unaffected. The reasoning is recorded next to the remaining constants so it does not get re-added. 2. Duplicate threat ID (blocking)The new row was numbered One behaviour note, not changed
Validation
I could not run Generated by Claude Code |
The spec-vs-public parity test requires every knowledge/ TM ID to appear in crates/bashkit/docs/threat-model.md. Claude-Session: https://claude.ai/code/session_01MJBT5na4uL5yZZXwwH1FMy
Motivation
grep/VFS traversal could materialize millions of matches and bypass shell execution deadlines, amplifying host memory and CPU usage (TM-DOS-106).max_count=Noneand eagersplitlines()made dense attacker-controlled files create huge in-memory object graphs.asyncio.to_threaddid not reliably stop the worker, so cancellation/timeouts were ineffective.Description
_OperationBudget,_BudgetExceeded, and session-work accounting onBashkitBackendincrates/bashkit-python/bashkit/deepagents.py._lines()iterator instead ofsplitlines(), and charge traversal bytes/files while walking in_files()so reads/glob/grep honor traversal/file/byte budgets._DEFAULT_GREP_MATCHES = 1000) and a matched-result byte ceiling (_MAX_GREP_RESULT_BYTES = 100_000), returnGrepResult(truncated=True)when budgets hit limits, and forward a cancellableagrep/aglobworker that sets the cancellation flag on task cancelation.crates/bashkit-python/tests/test_deepagents_backend.py) that exercise dense-file behavior and cooperative cancellation, and update documentation entries inknowledge/runtimes/python-package.mdandknowledge/security/threat-model.mdto record TM-DOS-106 mitigation.Testing
ruff format/ruff checkandpython -m py_compileon the modified Python module with no lint or syntax failures.maturin developin a venv and ranpytest crates/bashkit-python/tests/test_deepagents_backend.py, which passed (14 passed).pytest crates/bashkit-python/tests/suite in the prepared environment; modified tests passed (14 passed) while full test-collection of the entire Python test tree can require CI-only fixtures (bashkit_random_fs).tracemallocassertion passed in CI-local runs).Codex Task