Skip to content

fix(kanban): prevent worker session routing leaks - #69181

Closed
trymhaak wants to merge 2 commits into
NousResearch:mainfrom
trymhaak:fix/kanban-worker-session-env-routing
Closed

fix(kanban): prevent worker session routing leaks#69181
trymhaak wants to merge 2 commits into
NousResearch:mainfrom
trymhaak:fix/kanban-worker-session-env-routing

Conversation

@trymhaak

@trymhaak trymhaak commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • unconditionally remove every registered HERMES_SESSION_* / cron delivery-routing key from gateway-dispatched Kanban worker environments
  • prevent stale routing inherited from the gateway process from making worker-created child tasks auto-subscribe an unrelated chat or topic
  • preserve Kanban board, workspace, task, branch, profile, model, and credential propagation
  • extend the existing dispatcher regression to cover dispatch before the gateway binds its first session

Reproduction

A long-lived gateway had stale Telegram topic routing mirrored in os.environ. _default_spawn() copied that process environment directly into a detached Kanban worker. When that worker called kanban_create, get_session_env() treated the inherited Telegram context as its origin and auto-subscribed the child task. The task's terminal completion then woke the unrelated topic.

The first candidate reused the normal ContextVar bridge, but independent review found that its sanitizer preserves fallback environment values before session-context engagement. The updated regression sets the engagement latch to false, injects every key in the canonical routing registry, and proves the detached worker receives none of them.

Tests

python -m pytest tests/hermes_cli/test_kanban_db.py tests/tools/test_local_env_session_leak.py tests/gateway/test_session_context_inheritance.py -q -o 'addopts='
248 passed

The exact high-severity review reproducer failed before the updated production change and passes afterward. The 16 failures observed only when collecting all Kanban test modules into one non-canonical process were test-order/isolation issues: all 23 affected tests pass when their owning files/subsets run independently.

Also verified:

git diff --check
python -m py_compile hermes_cli/kanban_db.py tests/hermes_cli/test_kanban_db.py

Risk / rollback

Low risk. Detached Kanban workers have no conversation delivery ownership; explicit Kanban notification subscriptions remain stored in the board DB and are unaffected. The change strips only the existing session/delivery routing registry before reapplying the worker's board/profile/task pins. Revert the two commits to roll back.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cron Cron scheduler and job management sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 22, 2026
teknium1 pushed a commit that referenced this pull request Jul 26, 2026
A long-lived gateway can have platform routing (HERMES_SESSION_* /
HERMES_CRON_AUTO_DELIVER_*) mirrored in os.environ from a previous turn.
_default_spawn() copied that process environment verbatim into detached
kanban workers, so a worker calling kanban_create treated the inherited
chat/topic as its origin and auto-subscribed the child task — the task's
terminal notification then woke an unrelated chat.

Strip every registered session-context routing key from the worker env
unconditionally (the dispatcher is detached from every conversation);
board, workspace, task, branch, profile, model, and credential
propagation are unchanged.

Salvaged from PR #69181 (both commits squashed; the PR's second commit
fixed the first's engagement-latch assumption).
teknium1 pushed a commit that referenced this pull request Jul 26, 2026
A long-lived gateway can have platform routing (HERMES_SESSION_* /
HERMES_CRON_AUTO_DELIVER_*) mirrored in os.environ from a previous turn.
_default_spawn() copied that process environment verbatim into detached
kanban workers, so a worker calling kanban_create treated the inherited
chat/topic as its origin and auto-subscribed the child task — the task's
terminal notification then woke an unrelated chat.

Strip every registered session-context routing key from the worker env
unconditionally (the dispatcher is detached from every conversation);
board, workspace, task, branch, profile, model, and credential
propagation are unchanged.

Salvaged from PR #69181 (both commits squashed; the PR's second commit
fixed the first's engagement-latch assumption).
teknium1 pushed a commit that referenced this pull request Jul 26, 2026
A long-lived gateway can have platform routing (HERMES_SESSION_* /
HERMES_CRON_AUTO_DELIVER_*) mirrored in os.environ from a previous turn.
_default_spawn() copied that process environment verbatim into detached
kanban workers, so a worker calling kanban_create treated the inherited
chat/topic as its origin and auto-subscribed the child task — the task's
terminal notification then woke an unrelated chat.

Strip every registered session-context routing key from the worker env
unconditionally (the dispatcher is detached from every conversation);
board, workspace, task, branch, profile, model, and credential
propagation are unchanged.

Salvaged from PR #69181 (both commits squashed; the PR's second commit
fixed the first's engagement-latch assumption).
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #72241 — applied as one commit re-attributed to your GitHub handle (the original commits were authored under a local placeholder identity). Stripping stale HERMES_SESSION_*/cron routing keys from dispatched worker env closes the cross-profile auto-subscribe leak mechanism. Thanks!

@teknium1 teknium1 closed this Jul 26, 2026
wernerhp pushed a commit to wernerhp/hermes-agent that referenced this pull request Jul 27, 2026
…sion-env

Semantic conflict in hermes_cli/kanban_db.py _default_spawn():
upstream main 148497f (salvaged from NousResearch#69181) STRIPS every _VAR_MAP
session-routing key from the dispatched worker env, directly superseding
this PR's approach of FORWARDING HERMES_SESSION_* via
build_session_subprocess_env. A detached worker that inherits routing
auto-subscribes child tasks to an unrelated chat, so the strip is the
shipped, correct behavior. Resolved by taking main's strip; the PR's
_SUBPROCESS_FORWARD_VARS is a subset of _VAR_MAP so nothing new leaks.
send_message_tool.py origin-fallback and build_session_subprocess_env
remain (merged clean) — harmless when the env vars are absent.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
A long-lived gateway can have platform routing (HERMES_SESSION_* /
HERMES_CRON_AUTO_DELIVER_*) mirrored in os.environ from a previous turn.
_default_spawn() copied that process environment verbatim into detached
kanban workers, so a worker calling kanban_create treated the inherited
chat/topic as its origin and auto-subscribed the child task — the task's
terminal notification then woke an unrelated chat.

Strip every registered session-context routing key from the worker env
unconditionally (the dispatcher is detached from every conversation);
board, workspace, task, branch, profile, model, and credential
propagation are unchanged.

Salvaged from PR NousResearch#69181 (both commits squashed; the PR's second commit
fixed the first's engagement-latch assumption).
prmartinow pushed a commit to prmartinow/hermes-agent that referenced this pull request Aug 26, 2026
A long-lived gateway can have platform routing (HERMES_SESSION_* /
HERMES_CRON_AUTO_DELIVER_*) mirrored in os.environ from a previous turn.
_default_spawn() copied that process environment verbatim into detached
kanban workers, so a worker calling kanban_create treated the inherited
chat/topic as its origin and auto-subscribed the child task — the task's
terminal notification then woke an unrelated chat.

Strip every registered session-context routing key from the worker env
unconditionally (the dispatcher is detached from every conversation);
board, workspace, task, branch, profile, model, and credential
propagation are unchanged.

Salvaged from PR NousResearch#69181 (both commits squashed; the PR's second commit
fixed the first's engagement-latch assumption).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cron Cron scheduler and job management P3 Low — cosmetic, nice to have sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages 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.

3 participants