From 9bbad3cc10cc12b0ad3f76ee323b4e8e6d241cb9 Mon Sep 17 00:00:00 2001 From: memosr Date: Sat, 9 May 2026 14:46:27 +0530 Subject: [PATCH] fix(security): drop caller-controlled author override in kanban_comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comments are injected into the next worker's system prompt by build_worker_context() as '**{author}** (timestamp): {body}'. The previous code accepted args['author'] as a free-form override and exposed it on KANBAN_COMMENT_SCHEMA, which let a worker: 1. Receive a prompt-injection in a malicious task body. 2. Call kanban_comment with author='hermes-system' (or any other authoritative-looking name) on a sibling task. 3. The next worker assigned to that sibling task sees the forged comment in its boot context as what reads like a system-authored directive. Always derive author from HERMES_PROFILE (the dispatcher already sets this per worker at hermes_cli/kanban_db.py:3718), and remove the 'author' property from the tool schema so the LLM can't see the override surface. Cross-task commenting itself remains unrestricted (see #19713) — comments are the deliberate handoff channel between tasks; only the author-override surface is closed. Co-authored-by: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> --- tools/kanban_tools.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/kanban_tools.py b/tools/kanban_tools.py index 2326895554f..366252e385e 100644 --- a/tools/kanban_tools.py +++ b/tools/kanban_tools.py @@ -373,7 +373,16 @@ def _handle_comment(args: dict, **kw) -> str: body = args.get("body") if not body or not str(body).strip(): return tool_error("body is required") - author = args.get("author") or os.environ.get("HERMES_PROFILE") or "worker" + # Author is intentionally derived from the worker's own runtime + # identity, NOT from caller-supplied args. Comments are injected + # into the next worker's system prompt by ``build_worker_context`` + # as ``**{author}** (timestamp): {body}`` — accepting an + # ``args["author"]`` override let a worker forge a comment from + # an authoritative-looking name like ``hermes-system`` and poison + # the future-worker context with what reads as a system directive. + # Cross-task commenting itself remains unrestricted (see #19713) — + # comments are the deliberate handoff channel between tasks. + author = os.environ.get("HERMES_PROFILE") or "worker" try: kb, conn = _connect() try: @@ -656,13 +665,6 @@ KANBAN_COMMENT_SCHEMA = { "type": "string", "description": "Markdown-supported comment body.", }, - "author": { - "type": "string", - "description": ( - "Override author name. Defaults to the current " - "profile (HERMES_PROFILE env)." - ), - }, }, "required": ["task_id", "body"], },