Skip to content

fix: make gateway approvals human-readable - #46682

Draft
ReEvolutionWorld wants to merge 2 commits into
NousResearch:mainfrom
ReEvolutionWorld:codex/security-hardening
Draft

fix: make gateway approvals human-readable#46682
ReEvolutionWorld wants to merge 2 commits into
NousResearch:mainfrom
ReEvolutionWorld:codex/security-hardening

Conversation

@ReEvolutionWorld

Copy link
Copy Markdown

Summary

  • add a shared command approval summary builder for gateway approval prompts
  • render Action, Mode, Target, Category, Need, Reason, and Risk before Raw command across gateway adapters
  • add regression coverage for Telegram approval cards and summary classification

Context

This preserves the Hermes/ReBot approval UX hotfix that was verified in the running runtime at /opt/hermes. The goal is to make raw shell/code approval cards human-readable before the user sees the raw command.

Validation

  • python3 -m py_compile tools/approval.py gateway/run.py gateway/platforms/telegram.py gateway/platforms/slack.py gateway/platforms/feishu.py gateway/platforms/matrix.py gateway/platforms/discord.py gateway/platforms/qqbot/adapter.py gateway/platforms/qqbot/keyboards.py tests/gateway/test_telegram_approval_buttons.py tests/tools/test_approval.py
  • git diff --check HEAD~1..HEAD

Targeted pytest was attempted but the active local Python environment is missing PyYAML, so collection failed before tests ran.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery labels Jun 15, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for preserving the approval UX work. The human-first goal is still needed on current main: Telegram still renders the command before its reason at plugins/platforms/telegram/adapter.py:4581-4585, and the fallback does the same at gateway/run.py:18668-18674.

Problems

  • The adapter edits target paths removed by the bundled-platform migration in 5600105478ff; the active Telegram/Slack/Discord/Feishu/Matrix code is now in plugins/platforms/*/adapter.py. The PR test still imports the removed Telegram module at tests/gateway/test_telegram_approval_buttons.py:50 on the PR head.
  • gateway/platforms/slack.py:2266 retains a 2900-character preview while adding summary text to the same Block Kit section. That can exceed Slack's 3000-character section limit. Current main budgets this at plugins/platforms/slack/adapter.py:3259-3269.
  • tools/approval.py:819 labels curl/wget requests read-only unless -X/--request is present. curl -d, -F, and --upload-file can mutate without either flag.

Suggested changes

  • Port the renderer changes and tests to the active plugin adapter paths, plus QQBot, WhatsApp Cloud, and gateway/run.py fallback.
  • Use per-surface output budgets and conservative HTTP classification with mutation-flag tests.

Automated hermes-sweeper review.

@@ -2263,8 +2265,9 @@ async def send_exec_approval(
"type": "mrkdwn",
"text": (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section keeps the existing 2900-character preview and adds header/explanation/reason framing, so it can exceed Slack's 3000-character section-text limit and fail with invalid_blocks. Budget cmd_preview against the complete fixed framing; current main now does this in plugins/platforms/slack/adapter.py:3259-3269.

Comment thread tools/approval.py
if first in {"curl", "wget"} or " curl " in f" {lowered} ":
if re.search(r'\b(?:-X|--request)\s*(?:POST|PUT|PATCH|DELETE)\b', command, re.IGNORECASE):
return f"This will send a mutating HTTP request to {target or 'a network endpoint'}."
return f"This will make a read-only network request to {target or 'a network endpoint'}."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -d/--data, -F, and --upload-file can mutate a remote endpoint without -X or --request; this would tell the approver the request is read-only. Classify those flags as potentially mutating (or leave the effect unclear) and add regression coverage.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026

@GottZ GottZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was generated by AI during triage.

Summary

Two PRs touch approval-related behavior but address different root causes: #46682 restructures command approval prompts into human-readable summaries, while #63869 fixes QQBot direct-message routing by treating dm like c2c across outbound and authorization paths.

Related pull requests

  • #46682 related — (+309/-16) — author action required: the diff adds a reusable approval-summary classifier and places explanations before raw commands across gateway adapters, directly addressing unreadable approval prompts. Despite the keep_open review on #46682, the current diff targets adapter paths removed by the bundled-platform migration in 5600105478ff, imports the removed Telegram module in its test, can exceed Slack's 3000-character section limit, and incorrectly classifies mutating curl -d, -F, and --upload-file requests as read-only; the renderer and tests remain salvageable if ported to the active plugins/platforms/*/adapter.py paths with those correctness issues fixed.
  • #63869 [closed] related — (+36/-9) — duplicate fix: the diff consistently accepts dm alongside c2c in QQBot send, upload, keyboard, and interaction-authorization paths, matching the reported direct-message failure. Although closed, it remains relevant as evidence of the broad fix and as a duplicate of #40705, which covers the same paths through a shared is_private_chat_type() helper rather than nine repeated checks.

Duplicates

#63869 is a broad-scope duplicate of #40705; #31593 is the narrower authorization-only predecessor and #41801 is another broad-scope sibling. #46682 is not a duplicate of #63869 because it changes approval-prompt presentation rather than QQBot DM routing.

Suggested consolidation

For #46682, author action: rebase onto main, or split out the part that can merge—specifically preserve the shared human-first renderer and regression coverage, port them to the active plugins/platforms/*/adapter.py implementations, budget Slack text within its section limit, and classify body/upload forms of curl as mutating. This explicitly narrows the keep_open review's salvage path into required author work rather than recommending the current stale, high-risk diff. Keep #63869 closed as duplicate of #40705, with the duplicate chain recorded as #63869#40705; the two target PRs should not be consolidated into one patch because they address different causes.

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 29 kB of PR diffs, 2 kB of issue/PR text, 4 kB of discussion (3 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants