Skip to content

fix(gateway): Slack approval handler must fail closed when SLACK_ALLOWED_USERS unset#36861

Closed
dhyabi2 wants to merge 2 commits into
NousResearch:mainfrom
dhyabi2:fix/slack-approval-fail-closed
Closed

fix(gateway): Slack approval handler must fail closed when SLACK_ALLOWED_USERS unset#36861
dhyabi2 wants to merge 2 commits into
NousResearch:mainfrom
dhyabi2:fix/slack-approval-fail-closed

Conversation

@dhyabi2

@dhyabi2 dhyabi2 commented Jun 1, 2026

Copy link
Copy Markdown

What & why

_handle_approval_action (Slack Block-Kit) gates approval-button clicks behind if allowed_csv:. When SLACK_ALLOWED_USERS is unset (the default — it's not in the example configs), the entire auth block is skipped and execution falls through to processing the approval. Any workspace member who can see the message can click Approve always, persisting a dangerous-command allowlist entry to the operator's config.yaml. The in-code comment even notes button clicks bypass the normal message-auth flow "so we must check here as well" — but that check is disabled by default.

The analogous Telegram handler was already fixed to fail closed in #24457; this brings Slack in line.

The fix

Fail closed when SLACK_ALLOWED_USERS is unset: deny by default and require an explicit opt-in (SLACK_ALLOWED_USERS=* or GATEWAY_ALLOW_ALL_USERS) for no-restriction mode — mirroring the merged Telegram fix.

How to test

  • SLACK_ALLOWED_USERS unset, GATEWAY_ALLOW_ALL_USERS unset → approval click is rejected with the existing "Unauthorized approval click" warning.
  • SLACK_ALLOWED_USERS=* (or the clicking user listed) → click authorized, as before.
  • GATEWAY_ALLOW_ALL_USERS=true → opt-in no-restriction mode, click authorized.

Platforms

Logic-only change in gateway/platforms/slack.py.

Fixes #36848. Reported privately as GHSA-jg5x-hmg9-2q4c (still in triage); mirrors the already-merged Telegram fix #24457.

…WED_USERS unset

_handle_approval_action gated approval-button clicks behind
'if allowed_csv:', so when SLACK_ALLOWED_USERS was unset (the default) the
auth check was skipped entirely and any workspace member in the channel
could click 'Approve always', persisting a dangerous-command allowlist
entry. Fail closed by default and require an explicit opt-in
(SLACK_ALLOWED_USERS=* or GATEWAY_ALLOW_ALL_USERS), mirroring the merged
Telegram fix (NousResearch#24457).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Covers _handle_approval_action: denies when SLACK_ALLOWED_USERS unset and
GATEWAY_ALLOW_ALL_USERS unset; permits on wildcard, listed user, or
allow-all; denies unlisted user. Mirrors the Matrix/Telegram fail-closed
test style.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alt-glitch alt-glitch added type/security Security vulnerability or hardening P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/slack Slack app adapter area/auth Authentication, OAuth, credential pools labels Jun 1, 2026
@liuhao1024

Copy link
Copy Markdown
Contributor

Good security fix. The fail-closed logic is correct: when SLACK_ALLOWED_USERS is unset, approvals are denied unless GATEWAY_ALLOW_ALL_USERS is explicitly set to true/1/yes. Test coverage is comprehensive and mirrors the Telegram pattern (#24457). No issues found.

1 similar comment
@liuhao1024

Copy link
Copy Markdown
Contributor

Good security fix. The fail-closed logic is correct: when SLACK_ALLOWED_USERS is unset, approvals are denied unless GATEWAY_ALLOW_ALL_USERS is explicitly set to true/1/yes. Test coverage is comprehensive and mirrors the Telegram pattern (#24457). No issues found.

@teknium1

teknium1 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Thanks for catching this on a real exploit path — independent confirmation from several contributors is what got it prioritized.

The fail-open is being fixed in #41226 (open, pending review), a cross-adapter salvage that closes the same bug on Slack, Feishu, and Discord in one PR. For the Slack side we picked #33844 by @Dusk1e as canonical because it mirrors Telegram's _is_callback_user_authorized precedent most closely — it delegates to the gateway runner's central _is_user_authorized() so GATEWAY_ALLOWED_USERS, DM pairing, and GATEWAY_ALLOW_ALL_USERS are all honored before the env-only fail-closed fallback.

Your version is clean and well-tested, but it gates only on SLACK_ALLOWED_USERS + GATEWAY_ALLOW_ALL_USERS — an operator who restricts access via the central GATEWAY_ALLOWED_USERS (without setting the Slack-specific list) would still have button clicks denied for legitimate users. #33844 routes through the runner's central auth, which honors that central allowlist.

Holding this open until #41226 is reviewed/merged rather than closing it now — the credit stands either way.

@teknium1

teknium1 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Closing — the fail-open is now fixed on main via PR #41226 (merged: commits a317e54 / 410cb74 (Slack), 3fa15b3 (Feishu), f6f3636 (Discord)). The Slack side landed @Dusk1e's #33844 as canonical (delegates to the gateway runner's central auth, matching the Telegram precedent). Thanks again for the report and the fix — your contribution is credited in #41226.

@teknium1 teknium1 closed this Jun 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/slack Slack app adapter type/security Security vulnerability or hardening

Projects

None yet

4 participants