OpenClaw’s Slack Channel-ID Fix Shows Why Name-Based Allowlists Need Runtime Proof

OpenClaw’s Slack Channel-ID Fix Shows Why Name-Based Allowlists Need Runtime Proof

Slack bots are where agent security stops being abstract. A workspace channel looks friendly to humans — #general, #ops, #customer-escalations — but the API cares about channel IDs, account tokens, membership, scopes, and method-specific behavior. OpenClaw PR #95313 fixes a mismatch in that translation layer, and the lesson is broader than Slack: name-based allowlists need runtime proof, or they are just policy-shaped vibes.

The bug sits in a narrow but important path. OpenClaw Slack tools can perform read-like actions such as reading messages, downloading files, listing pins, and listing reactions. Operators may configure access by human-readable channel name when dangerouslyAllowNameMatching is enabled. But a tool call can arrive with a Slack channel ID rather than the configured name. Before the patch, those channel-ID reads could be rejected before OpenClaw resolved the name allowlist, even when the ID represented an allowed channel.

That sounds like a convenience bug, and partly it is. But convenience is the surface. The underlying problem is identity proof. Humans write policy in names because names are readable. APIs execute policy against IDs because IDs are stable. Agents sit in the middle, which means they need a trustworthy bridge between the two.

Names are UX; IDs are security

PR #95313 adds that bridge in two ways. First, when the current context includes a channel name and the requested target matches the current channel, OpenClaw can use that context to re-check authorization. Second, when an action only has a channel ID and name matching is explicitly enabled, OpenClaw lazily calls Slack’s conversations.info API to resolve authoritative metadata, including the channel’s id and name, and then re-runs the read authorization with the resolved name. If no allowed name is found, the system fails closed.

The patch is not tiny: 246 additions, 19 deletions, and 6 changed files across Slack action runtime, channel-type helpers, threading tool context, and shared channel plugin types. The test evidence is also the right shape: pnpm test:extension slack reports 101 files and 1,334 tests passed; targeted Vitest covers 2 files and 74 tests; pnpm tsgo:extensions and git diff --check pass. The added fixtures cover same-context channel-name authorization, rejection of a different target channel despite an allowed current context, resolving names before allowlist failure, resolving name-keyed allow before wildcard fallback denial, and returning conversation names from the channel-type helper.

The most interesting review comment is not “does it work?” It is whether currentChannelName, now a shared threading-tool context field, is semantically trusted. Producer and consumer need to agree that this value is the human-readable name for the same Slack channel being authorized, not a convenient label that happened to be nearby. That distinction is easy to wave away in application code and painful to rediscover in an incident review.

Name matching is already labeled dangerously for a reason. Slack channel names can change. Workspaces can have naming conventions that collide conceptually. Shared channels, archived channels, private channels, and enterprise grid setups add more surface area. A name is excellent for humans scanning a config file. It is less excellent as the final authority boundary. If a platform offers name-based policy, it owes the operator provenance: which token resolved the name, when it was resolved, which ID it mapped to, whether it came from the current event or a fresh API call, and whether the target matched exactly.

The operator checklist is bigger than this PR

For OpenClaw operators, the immediate recommendation is boring: prefer channel IDs for strict allowlists where possible. IDs are uglier, but they are what the API actually uses. If you enable dangerouslyAllowNameMatching, use it knowingly and look for the protections this PR adds: same-target checks, authoritative API resolution, fail-closed behavior, and tests that prevent wildcard fallback from overriding a specific denial.

For platform builders, steal the pattern and apply it everywhere agents translate human language into API targets. Slack has channels. Discord has channel IDs, thread IDs, guild IDs, and DMs. Telegram has chats, topics, and message references. Email has aliases, labels, folder IDs, and forwarding rules. GitHub has repo names, node IDs, installation IDs, and org scopes. Every friendly name used in an instruction or config needs a provenance story before it becomes an authorization decision.

The broader OpenClaw context reinforces the point. On June 19, the project was already tightening Slack identity defaults around member-info. Now this PR tightens channel-read authorization. These are not random Slack nits. They are symptoms of a platform growing into a multi-surface runtime where agents can read, react, download, inspect, and act across workspaces. The risk is rarely “the model becomes evil.” The risk is usually one missing scope check in a helper that everybody assumed was merely plumbing.

There is a product lesson too: the best agent tools should make secure configuration less miserable. Humans do not want to manage raw IDs everywhere. They want #ops. That is reasonable. But the runtime cannot simply inherit the human-friendly string and hope. It should resolve, cache carefully, show what it resolved, and audit the decision. A status or doctor surface that says “#ops → C0123456789 via conversations.info at 14:03 UTC using workspace X” is not overkill for enterprise agents. It is how operators learn to trust the system.

The editorial take: this is not “Slack reads now work with channel names.” It is that agent authorization has to translate human policy into API identity without hand-waving. Names are UX. IDs and proofs are security. Anything in between needs tests, provenance, and a healthy suspicion of convenience.

Sources: OpenClaw PR #95313, Slack conversations.info documentation