Skip to content

Coerce session.steer/redirect text against non-string JSON - #79319

Closed
aydnOktay wants to merge 1 commit into
NousResearch:mainfrom
aydnOktay:fix/session-steer-text-coerce
Closed

Coerce session.steer/redirect text against non-string JSON#79319
aydnOktay wants to merge 1 commit into
NousResearch:mainfrom
aydnOktay:fix/session-steer-text-coerce

Conversation

@aydnOktay

Copy link
Copy Markdown
Contributor

Summary

  • session.steer / session.redirect run inline (not in _LONG_HANDLERS); bare (params.get("text") or "").strip() AttributeErrors on list/int text and can tear down the stdin/WS reader.
  • Coerce with str(... or "") before .strip(); same hardening for llm.oneshot template/task and handoff.request platform.
  • Regression tests: null → 4002, int text queued as "42", list text must not crash.

…ing JSON

Inline RPCs called .strip() on raw params; list/int text raised AttributeError and could tear down the reader thread.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Aug 5, 2026
later0day added a commit to later0day/hermes-agent that referenced this pull request Aug 7, 2026
Upstream documents the "fail closed" rationale next to the relay branch in
_deliver_result, and the fork's diff removed that three-line comment.  In
tandem the fork added a DingTalk-specific session_webhook fallback block
above the relay branch (lines 2298-2338).  The webhook is keyed off the
job's ORIGIN — not the transport — so a relay-fronted DingTalk job whose
relay send failed would fall through into the webhook block and
re-deliver behind the relay's back, using a credential the connector does
not own.  That is exactly the double-delivery the fail-closed branch
existed to prevent.

Fix:
  1. Restore the fail-closed rationale comment above the relay branch.
  2. Gate the DingTalk session_webhook fallback on
     `not (transport is not None and transport.is_relay)` so it stays
     available for standalone / native transports (where the process
     legitimately owns the credential) but never re-delivers on a
     relay-fronted target.

Guards (tests/cron/test_relay_delivery_fail_closed.py):
  - test_failed_relay_delivery_does_not_retry_standalone
  - test_raising_relay_delivery_does_not_retry_standalone
  - test_relay_fronted_dingtalk_does_not_bypass_via_session_webhook
  - test_native_dingtalk_still_uses_the_session_webhook_fallback
  - test_relay_fail_closed_comment_documents_the_invariant

Two-way negative control: removing the comment triggers test 5; removing
the relay gate triggers test 3.  Native (non-relay) DingTalk continues to
use the captured webhook exactly as before.

SECURITY.md §2.6 / NousResearch#79319 — no code-path fail-open on relay ownership.
@aydnOktay

Copy link
Copy Markdown
Contributor Author

Closing to concentrate review on a single linked product bug: #89979.

@aydnOktay aydnOktay closed this Aug 19, 2026
@aydnOktay

Copy link
Copy Markdown
Contributor Author

Closing to concentrate review on a single linked product bug: #89979.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants