fix(security): gate slash commands by sender
This commit is contained in:
@@ -26,7 +26,7 @@ import { sendMessageSlack } from "../../send.js";
|
||||
import type { SlackMessageEvent } from "../../types.js";
|
||||
|
||||
import { allowListMatches, resolveSlackUserAllowed } from "../allow-list.js";
|
||||
import { isSlackSenderAllowListed, resolveSlackEffectiveAllowFrom } from "../auth.js";
|
||||
import { resolveSlackEffectiveAllowFrom } from "../auth.js";
|
||||
import { resolveSlackChannelConfig } from "../channel-config.js";
|
||||
import { normalizeSlackChannelType, type SlackMonitorContext } from "../context.js";
|
||||
import { resolveSlackMedia, resolveSlackThreadStarter } from "../media.js";
|
||||
@@ -217,18 +217,34 @@ export async function prepareSlackMessage(params: {
|
||||
return null;
|
||||
}
|
||||
|
||||
const commandAuthorized =
|
||||
isSlackSenderAllowListed({
|
||||
allowListLower: allowFromLower,
|
||||
senderId,
|
||||
senderName,
|
||||
}) && channelUserAuthorized;
|
||||
|
||||
const hasAnyMention = /<@[^>]+>/.test(message.text ?? "");
|
||||
const allowTextCommands = shouldHandleTextCommands({
|
||||
cfg,
|
||||
surface: "slack",
|
||||
});
|
||||
|
||||
const ownerAuthorized = allowListMatches({
|
||||
allowList: allowFromLower,
|
||||
id: senderId,
|
||||
name: senderName,
|
||||
});
|
||||
const channelUsersAllowlistConfigured =
|
||||
isRoom && Array.isArray(channelConfig?.users) && channelConfig.users.length > 0;
|
||||
const channelCommandAuthorized =
|
||||
isRoom && channelUsersAllowlistConfigured
|
||||
? resolveSlackUserAllowed({
|
||||
allowList: channelConfig?.users,
|
||||
userId: senderId,
|
||||
userName: senderName,
|
||||
})
|
||||
: false;
|
||||
const commandAuthorized = ownerAuthorized || channelCommandAuthorized;
|
||||
|
||||
if (allowTextCommands && isRoomish && hasControlCommand(message.text ?? "", cfg) && !commandAuthorized) {
|
||||
logVerbose(`Blocked slack control command from unauthorized sender ${senderId}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const shouldRequireMention = isRoom
|
||||
? (channelConfig?.requireMention ?? ctx.defaultRequireMention)
|
||||
: false;
|
||||
|
||||
@@ -167,6 +167,7 @@ export function registerSlackMonitorSlashCommands(params: {
|
||||
const isDirectMessage = channelType === "im";
|
||||
const isGroupDm = channelType === "mpim";
|
||||
const isRoom = channelType === "channel" || channelType === "group";
|
||||
const isRoomish = isRoom || isGroupDm;
|
||||
|
||||
if (
|
||||
!ctx.isChannelAllowed({
|
||||
@@ -270,14 +271,16 @@ export function registerSlackMonitorSlashCommands(params: {
|
||||
|
||||
const sender = await ctx.resolveUserName(command.user_id);
|
||||
const senderName = sender?.name ?? command.user_name ?? command.user_id;
|
||||
const channelUserAllowed = isRoom
|
||||
const channelUsersAllowlistConfigured =
|
||||
isRoom && Array.isArray(channelConfig?.users) && channelConfig.users.length > 0;
|
||||
const channelUserAllowed = channelUsersAllowlistConfigured
|
||||
? resolveSlackUserAllowed({
|
||||
allowList: channelConfig?.users,
|
||||
userId: command.user_id,
|
||||
userName: senderName,
|
||||
})
|
||||
: true;
|
||||
if (isRoom && !channelUserAllowed) {
|
||||
: false;
|
||||
if (channelUsersAllowlistConfigured && !channelUserAllowed) {
|
||||
await respond({
|
||||
text: "You are not authorized to use this command here.",
|
||||
response_type: "ephemeral",
|
||||
@@ -285,6 +288,22 @@ export function registerSlackMonitorSlashCommands(params: {
|
||||
return;
|
||||
}
|
||||
|
||||
const ownerAllowed = allowListMatches({
|
||||
allowList: effectiveAllowFromLower,
|
||||
id: command.user_id,
|
||||
name: senderName,
|
||||
});
|
||||
if (isRoomish && ctx.useAccessGroups && !(ownerAllowed || channelUserAllowed)) {
|
||||
await respond({
|
||||
text: "You are not authorized to use this command.",
|
||||
response_type: "ephemeral",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isRoomish) {
|
||||
commandAuthorized = ctx.useAccessGroups ? ownerAllowed || channelUserAllowed : true;
|
||||
}
|
||||
|
||||
if (commandDefinition && supportsInteractiveArgMenus) {
|
||||
const menu = resolveCommandArgMenu({
|
||||
command: commandDefinition,
|
||||
@@ -313,7 +332,6 @@ export function registerSlackMonitorSlashCommands(params: {
|
||||
|
||||
const channelName = channelInfo?.name;
|
||||
const roomLabel = channelName ? `#${channelName}` : `#${command.channel_id}`;
|
||||
const isRoomish = isRoom || isGroupDm;
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
channel: "slack",
|
||||
|
||||
Reference in New Issue
Block a user