Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 1 addition & 48 deletions gateway/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
from contextvars import copy_context
from pathlib import Path
from datetime import datetime
from typing import Callable, Dict, Optional, Any, List, Union
from typing import Dict, Optional, Any, List, Union

# account_usage imports the OpenAI SDK chain (~230 ms). Only needed by
# /usage; we still import it at module top in the gateway because test
Expand Down Expand Up @@ -1447,17 +1447,6 @@ def _profile_runtime_scope(profile_home: "Path"):
"singularity_image": "TERMINAL_SINGULARITY_IMAGE",
"modal_image": "TERMINAL_MODAL_IMAGE",
"daytona_image": "TERMINAL_DAYTONA_IMAGE",
"tenki_image": "TERMINAL_TENKI_IMAGE",
"tenki_api_endpoint": "TERMINAL_TENKI_API_ENDPOINT",
"tenki_workspace_id": "TERMINAL_TENKI_WORKSPACE_ID",
"tenki_project_id": "TERMINAL_TENKI_PROJECT_ID",
"tenki_name_prefix": "TERMINAL_TENKI_NAME_PREFIX",
"tenki_allow_inbound": "TERMINAL_TENKI_ALLOW_INBOUND",
"tenki_allow_outbound": "TERMINAL_TENKI_ALLOW_OUTBOUND",
"tenki_max_duration": "TERMINAL_TENKI_MAX_DURATION",
"tenki_idle_timeout": "TERMINAL_TENKI_IDLE_TIMEOUT",
"tenki_pause_retention": "TERMINAL_TENKI_PAUSE_RETENTION",
"tenki_sync_hermes_home": "TERMINAL_TENKI_SYNC_HERMES_HOME",
"ssh_host": "TERMINAL_SSH_HOST",
"ssh_user": "TERMINAL_SSH_USER",
"ssh_port": "TERMINAL_SSH_PORT",
Expand Down Expand Up @@ -6365,7 +6354,6 @@ async def start(self) -> bool:
adapter.set_session_store(self.session_store)
adapter.set_busy_session_handler(self._handle_active_session_busy_message)
adapter.set_topic_recovery_fn(self._recover_telegram_topic_thread_id)
adapter.set_authorization_check(self._make_adapter_auth_check(adapter.platform))
adapter._busy_text_mode = self._busy_text_mode
Comment on lines 6354 to 6357

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 Authorization check callback chain removed, disabling Slack thread prompt injection mitigation (security)

The PR removes _make_adapter_auth_check() (a 30-line closure factory that wrapped _is_user_authorized from authz_mixin.py) and deletes all three adapter.set_authorization_check(self._make_adapter_auth_check(adapter.platform)) calls from the gateway's adapter lifecycle paths:

  1. start() at line 6356
  2. _platform_reconnect_watcher() at line 7164
  3. _start_one_profile_adapters() at line 7820

The BasePlatformAdapter._authorization_check attribute defaults to None (base.py:2317). The _is_sender_authorized() method (base.py:2764) returns None when no check is registered — the exact condition introduced by this removal.

The Slack adapter at plugins/platforms/slack/adapter.py:3675 calls self._is_sender_authorized(msg_user, ...) during thread context fetching. At line 3678, the guard if is_authorized is False: uses identity comparison — None is not False, so trust_tag = "[unverified] " is never assigned. All thread-context messages from third-party senders in shared channels are presented to the LLM as authoritative input without the mitigation header (adapter.py:3688-3697) that instructs the model to treat unverified content as background reference.

Additionally, Callable was removed from the typing imports (line 44) since _make_adapter_auth_check was its only consumer in run.py.

The test suite (tests/gateway/test_slack.py) still mocks set_authorization_check() directly on adapters, giving false confidence that the production path works.

💡 Suggestion: Restore the _make_adapter_auth_check method and reinstate the three adapter.set_authorization_check() calls. If the feature was intentionally removed, the cleanup is incomplete — set_authorization_check() and _is_sender_authorized() remain on BasePlatformAdapter (base.py:2750-2786), the Slack adapter still calls _is_sender_authorized() (adapter.py:3675), and the test suite still exercises the feature via direct mock calls. Either restore the production wiring or complete the removal by also cleaning up the base class interface, the Slack adapter consumer code, and the tests.

📋 Prompt for AI Agents

In gateway/run.py: (1) Restore Callable to the typing import line (currently from typing import Dict, Optional, Any, List, Union — add back Callable). (2) After _create_adapter() ends at line 7987, re-insert the _make_adapter_auth_check method (the deleted closure factory that wraps _is_user_authorized). (3) At each of the three adapter setup sites, add adapter.set_authorization_check(self._make_adapter_auth_check(adapter.platform)) after the adapter.set_topic_recovery_fn(...) line: in start() after line 6356, in _platform_reconnect_watcher() after line 7164, in _start_one_profile_adapters() after line 7820. The code to add at each site is: adapter.set_authorization_check(self._make_adapter_auth_check(adapter.platform)). The deleted method (from the diff context) built a callback via SessionSource and _is_user_authorized — use that same implementation. If this feature is being deliberately removed instead, also remove set_authorization_check() and _is_sender_authorized() from gateway/platforms/base.py (lines 2750-2786), remove the [unverified] tagging logic from plugins/platforms/slack/adapter.py (lines 3669-3697), and update tests/gateway/test_slack.py to remove direct set_authorization_check() mock calls.


# Try to connect
Expand Down Expand Up @@ -7174,7 +7162,6 @@ async def _platform_reconnect_watcher(self) -> None:
adapter.set_session_store(self.session_store)
adapter.set_busy_session_handler(self._handle_active_session_busy_message)
adapter.set_topic_recovery_fn(self._recover_telegram_topic_thread_id)
adapter.set_authorization_check(self._make_adapter_auth_check(adapter.platform))
adapter._busy_text_mode = self._busy_text_mode

# Reconnect after an outage: preserve the platform's
Expand Down Expand Up @@ -7831,7 +7818,6 @@ async def _start_one_profile_adapters(
adapter.set_session_store(self.session_store)
adapter.set_busy_session_handler(self._handle_active_session_busy_message)
adapter.set_topic_recovery_fn(self._recover_telegram_topic_thread_id)
adapter.set_authorization_check(self._make_adapter_auth_check(adapter.platform))
adapter._busy_text_mode = self._busy_text_mode

try:
Expand Down Expand Up @@ -8000,39 +7986,6 @@ def _create_adapter(

return None

def _make_adapter_auth_check(
self,
platform: Platform,
) -> Callable[[str, Optional[str], Optional[str]], bool]:
"""Build a platform-bound auth callback for adapter use.

Adapters that fetch external context (e.g. Slack
``conversations.replies``) call this through
``BasePlatformAdapter._is_sender_authorized`` to mark non-allowlisted
senders as unverified in LLM context, mitigating indirect prompt
injection from third parties in shared threads/channels.

The returned callback delegates to :meth:`_is_user_authorized` so the
full auth chain — platform allowlists, group allowlists, pairing
store, allow-all flags — stays the single source of truth.
"""
def check(
user_id: str,
chat_type: Optional[str] = None,
chat_id: Optional[str] = None,
) -> bool:
if not user_id:
return False
source = SessionSource(
platform=platform,
chat_id=chat_id or "",
chat_type=chat_type or "group",
user_id=user_id,
)
return self._is_user_authorized(source)
return check





Expand Down
2 changes: 1 addition & 1 deletion scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@

# Auto-extracted from noreply emails + manual overrides
AUTHOR_MAP = {
"5823452+sgabel@users.noreply.github.com": "sgabel", # PR #13139 salvage (redact secrets in user-facing approval prompts)
"cyb3rwr3n@users.noreply.github.com": "cyb3rwr3n", # PR #11333 salvage (sanitize FTS5 queries for natural-language recall in holographic memory)
"9350182+codexGW@users.noreply.github.com": "codexGW", # PR #12302 salvage (Discord raw <@!ID> mention detection + drop bare mention-only pings)
"186512915+lEWFkRAD@users.noreply.github.com": "lEWFkRAD", # PR #53848 salvage (stream the MoA aggregator response to the user)
Expand Down Expand Up @@ -195,6 +194,7 @@
"290859878+synapsesx@users.noreply.github.com": "synapsesx",
"157689911+itsflownium@users.noreply.github.com": "itsflownium",
"dirtyren@users.noreply.github.com": "dirtyren",
"92324143+ypwcharles@users.noreply.github.com": "ypwcharles",
"mailtowbd@gmail.com": "marco0158",
"157793278+jacobmansonlkevincc@users.noreply.github.com": "lkevincc0",
"121278003+Cossackx@users.noreply.github.com": "Cossackx", # PR #52528 salvage (Windows hermes-shim resolution + prefer --update on recovery; #52378)
Expand Down
Loading