security(tui): strip stale dangerous confirmations on session resume - #60394
security(tui): strip stale dangerous confirmations on session resume#60394isheng-eqi wants to merge 2 commits into
Conversation
The gateway already strips stale dangerous-confirmation text from replayed history (NousResearch#60110, NousResearch#60117 — fix for NousResearch#59607). The TUI gateway has two session resume paths that sanitize replay history but do not strip stale dangerous confirmations, leaving the same vulnerability unaddressed in TUI sessions. Add strip_stale_dangerous_confirmations() after sanitize_replay_history() in both TUI resume paths (resume_session and the WebUI resume path). Refs: NousResearch#59607, NousResearch#60110, NousResearch#60117
|
Thanks for tracing the TUI sibling of the gateway expiry fix. The normal TUI cold-resume premise is verified on current main: Problems
Suggested changes
Automated hermes-sweeper review. |
GottZ
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
Summary
Two PRs address the TUI sibling of #59607. Both apply the same expiry helper to the eager and deferred cold-resume paths, but neither protects the lazy/watch resume path, and their tests cover the helper rather than the actual resume wiring.
Related pull requests
- #60209 [closed]
duplicate— (+64/-1) — superseded duplicate: The diff adds stale-confirmation expiry after replay sanitization in two cold-resume paths plus helper-level tests, but misses lazy/watch resume; this closed PR remains relevant as the contaminated-branch predecessor that was rebuilt as #60394. - #60394
related— (+64/-1) — keep open with a salvage path: The two cold-resume call sites are useful, but the diff leaves raw history unexpired in the lazy/watch path and does not test session.resume wiring. This is consistent with the automated keep-open review, with salvage requiring coverage of the lazy branch and resume-level tests for deferred, eager, and lazy modes.
Duplicates
#60209 and #60394 contain essentially the same change; #60394 is the clean-base replacement for the closed #60209.
Suggested consolidation
Keep #60394 open with a salvage path: preserve its eager and deferred cold-resume expiry calls, add expiry before the lazy/watch deferred record is constructed, and replace or supplement the helper-only tests with stale/fresh session.resume coverage across deferred, eager, and lazy modes. Treat #60209 as the superseded duplicate of #60394 and leave it closed.
Complex graph
flowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
subgraph Dup60209 ["PRs duplicating each other"]
P60209["PR #60209 (closed)"]
P60394["PR #60394 (open)"]
end
class P60209 closed
class P60394 open
class P60394 target
click P60209 "https://github.com/NousResearch/hermes-agent/pull/60209"
click P60394 "https://github.com/NousResearch/hermes-agent/pull/60394"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).
Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 10 kB of PR diffs, 2 kB of issue/PR text, <1 kB of discussion (1 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.
What does this PR do?
The TUI gateway has two session resume paths that strip dangling tool-call tails but do not expire stale dangerous-confirmation text — unlike the main gateway, which already does this (#60110, #60117).
When a user confirms a destructive action in a TUI session, that confirmation text persists. On resume, the model could re-interpret an unrelated message as a fresh confirmation and re-trigger the destructive action.
Related Issue
Fixes the TUI sibling path of #59607.
Type of Change
Changes Made
tui_gateway/server.py: Importstrip_stale_dangerous_confirmations, add call aftersanitize_replay_history()in both TUI resume pathstests/tui_gateway/test_stale_confirmation_resume.py: 4 tests covering stale/fresh confirmation, expiry window, and dangerous pattern detectionHow to Test