fix(slack): gate message files before metadata fetch

This commit is contained in:
dsad 2026-06-30 02:43:15 +03:00 committed by Teknium
parent 856b604b4a
commit e1883df75e
No known key found for this signature in database
2 changed files with 57 additions and 11 deletions

View file

@ -3942,22 +3942,25 @@ class SlackAdapter(BasePlatformAdapter):
# both as DM-style persistent conversations.
is_one_to_one_dm = channel_type == "im"
# Early auth check: reject unauthorized users before any API calls
# (thread context fetch, user name resolution, file downloads).
# Pattern matches Telegram fix #54164 — gate at the adapter level
# BEFORE event construction consumes resources.
if user_id:
# Reject unauthorized users before thread lookups, name resolution,
# or file downloads. The final gateway runner auth check happens
# after MessageEvent construction, so adapter-side media fetches need
# the same auth chain up front.
_runner = getattr(getattr(self, "_message_handler", None), "__self__", None)
_auth_fn = getattr(_runner, "_is_user_authorized", None)
if user_id and callable(_auth_fn):
_source = self.build_source(
chat_id=channel_id, chat_name="",
chat_id=channel_id,
chat_name="",
chat_type="dm" if is_dm else "group",
user_id=user_id, user_name="",
user_id=user_id,
user_name="",
)
_runner = getattr(getattr(self, "_message_handler", None), "__self__", None)
_auth_fn = getattr(_runner, "_is_user_authorized", None)
if callable(_auth_fn) and not _auth_fn(_source):
if not _auth_fn(_source):
logger.warning(
"[Slack] Early reject of unauthorized user %s in channel %s",
user_id, channel_id,
user_id,
channel_id,
)
return

View file

@ -1911,6 +1911,49 @@ class TestIncomingDocumentHandling:
assert os.path.exists(msg_event.media_urls[0])
assert msg_event.media_types == [SUPPORTED_VIDEO_TYPES[".mp4"]]
@pytest.mark.asyncio
async def test_unauthorized_message_does_not_fetch_file_info(
self,
adapter,
monkeypatch,
):
"""Global gateway auth must run before Slack file metadata fetches."""
monkeypatch.delenv("SLACK_ALLOW_ALL_USERS", raising=False)
monkeypatch.delenv("GATEWAY_ALLOW_ALL_USERS", raising=False)
monkeypatch.delenv("SLACK_ALLOWED_USERS", raising=False)
monkeypatch.setenv("GATEWAY_ALLOWED_USERS", "U_ALLOWED")
class Runner:
def _is_user_authorized(self, source):
return source.user_id == "U_ALLOWED"
async def handle(self, _event):
raise AssertionError("gateway handler should not run")
adapter._message_handler = Runner().handle
adapter._app.client.files_info = AsyncMock()
await adapter._handle_slack_message(
{
"type": "message",
"channel": "D123",
"channel_type": "im",
"user": "U_INTRUDER",
"text": "please read this",
"ts": "1234567890.000001",
"files": [
{
"id": "FSECRET",
"mimetype": "text/plain",
"name": "secret.txt",
}
],
}
)
adapter._app.client.files_info.assert_not_awaited()
adapter.handle_message.assert_not_called()
@pytest.mark.asyncio
async def test_download_failure_is_surfaced_in_message_text(self, adapter):
"""Attachment download failures (401/403/HTML-body/etc.) should be