@openclaw/slack 2026.5.12-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-inspect-D7AZNs8C.js +77 -0
- package/dist/account-inspect-api.js +10 -0
- package/dist/accounts-ClAPP5ry.js +139 -0
- package/dist/accounts.runtime-DDVcLJUI.js +2 -0
- package/dist/action-runtime-e2UhRsNx.js +350 -0
- package/dist/action-runtime.runtime-BFcqMbOm.js +2 -0
- package/dist/actions-CYLFK-Zy.js +292 -0
- package/dist/actions.runtime-CO3OaTLb.js +2 -0
- package/dist/allow-list-BPnnlRPL.js +82 -0
- package/dist/api.js +21 -0
- package/dist/approval-handler.runtime-CmeRr9qA.js +256 -0
- package/dist/blocks-input-CwTFVImV.js +29 -0
- package/dist/blocks-render-BIDw-Pom.js +161 -0
- package/dist/channel-DRjHBTDB.js +1020 -0
- package/dist/channel-api-B_nZwosg.js +20 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-entry.js +22 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.setup-Cayn7afd.js +73 -0
- package/dist/client-CPe4GmDR.js +103 -0
- package/dist/config-api-B_jq4NJW.js +2 -0
- package/dist/config-schema-D9B5LB_L.js +167 -0
- package/dist/configured-state.js +11 -0
- package/dist/contract-api.js +5 -0
- package/dist/directory-config-B3JiHeB7.js +54 -0
- package/dist/directory-contract-api.js +2 -0
- package/dist/directory-live-Bf16GwDh.js +133 -0
- package/dist/doctor-contract-KUjHnkQm.js +147 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/errors-BYFHR24f.js +109 -0
- package/dist/exec-approvals-7xUNgLi9.js +58 -0
- package/dist/group-policy-CyLUK6My.js +41 -0
- package/dist/http-routes-api.js +2 -0
- package/dist/inbound-contract-test-api.js +3 -0
- package/dist/index.js +33 -0
- package/dist/interactive-replies-api.js +2 -0
- package/dist/interactive-replies-qAIfuBor.js +173 -0
- package/dist/magic-string.es-BMaGRRZ1.js +1011 -0
- package/dist/media-D1XCd1uP.js +469 -0
- package/dist/message-tool-api-6lowf9zE.js +104 -0
- package/dist/message-tool-api.js +2 -0
- package/dist/monitor-a97o17G6.js +13 -0
- package/dist/mrkdwn-Cax-eSfK.js +6 -0
- package/dist/outbound-adapter-B_5sEhCg.js +174 -0
- package/dist/outbound-payload-test-api.js +2 -0
- package/dist/outbound-payload.test-harness-CVCamg1x.js +13558 -0
- package/dist/pipeline.runtime-DT0hLnq2.js +1379 -0
- package/dist/plugin-routes-DtTPmga1.js +20 -0
- package/dist/prepare-D3YqV8jB.js +1482 -0
- package/dist/prepare.test-helpers-DVcjRhfG.js +49 -0
- package/dist/probe-3eZf1FjI.js +42 -0
- package/dist/provider-D7uAN3Fq.js +3235 -0
- package/dist/registry-CeaoNfoP.js +39 -0
- package/dist/replies-Xe_jMR6o.js +139 -0
- package/dist/reply-blocks-Z5l6_R6H.js +14 -0
- package/dist/resolve-allowlist-common-Bk3clYPK.js +43 -0
- package/dist/resolve-channels-BRYqyNVJ.js +81 -0
- package/dist/resolve-users-Bd_SdP8j.js +113 -0
- package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/room-context-0vovmZPU.js +787 -0
- package/dist/runtime-Bo-KHM-F.js +8 -0
- package/dist/runtime-api-Dd1xIV5v.js +9 -0
- package/dist/runtime-api.js +14 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/scopes-CDevO8jg.js +74 -0
- package/dist/secret-contract-Bo6lbSkh.js +141 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-BtHGnD3d.js +51 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-D_A9kL-C.js +721 -0
- package/dist/send.runtime-BRE_ncCU.js +2 -0
- package/dist/send.runtime-_l76lUuL.js +2 -0
- package/dist/setup-core-B9NetDkM.js +320 -0
- package/dist/setup-entry.js +15 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/setup-surface-D88QBVOW.js +128 -0
- package/dist/shared-D8U42xFL.js +208 -0
- package/dist/slash-commands.runtime-22kgyst2.js +19 -0
- package/dist/slash-dispatch.runtime-BJgT0jwV.js +32 -0
- package/dist/slash-plugin-commands.runtime-CF-n3MeP.js +2 -0
- package/dist/slash-skill-commands.runtime-BMs0VjTe.js +7 -0
- package/dist/streaming-compat-RkZgTmQ2.js +43 -0
- package/dist/target-parsing-CQmv-iSm.js +55 -0
- package/dist/targets-B1tYCAr6.js +2 -0
- package/dist/test-api.js +8 -0
- package/dist/thread-ts-C2x7c5PP.js +24 -0
- package/openclaw.plugin.json +2405 -0
- package/package.json +84 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
2
|
+
//#region extensions/slack/src/runtime.ts
|
|
3
|
+
const { setRuntime: setSlackRuntime, clearRuntime: clearSlackRuntime, tryGetRuntime: getOptionalSlackRuntime } = createPluginRuntimeStore({
|
|
4
|
+
pluginId: "slack",
|
|
5
|
+
errorMessage: "Slack runtime not initialized"
|
|
6
|
+
});
|
|
7
|
+
//#endregion
|
|
8
|
+
export { setSlackRuntime as n, getOptionalSlackRuntime as t };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "./target-parsing-CQmv-iSm.js";
|
|
2
|
+
import "./channel-api-B_nZwosg.js";
|
|
3
|
+
import "./config-api-B_jq4NJW.js";
|
|
4
|
+
import { createActionGate as createActionGate$1, imageResultFromFile, jsonResult, readNumberParam, readReactionParams, readStringParam, withNormalizedTimestamp } from "openclaw/plugin-sdk/channel-actions";
|
|
5
|
+
import "openclaw/plugin-sdk/account-id";
|
|
6
|
+
import "openclaw/plugin-sdk/channel-status";
|
|
7
|
+
import "openclaw/plugin-sdk/channel-plugin-common";
|
|
8
|
+
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
9
|
+
export { readNumberParam as a, withNormalizedTimestamp as c, loadOutboundMediaFromUrl as i, imageResultFromFile as n, readReactionParams as o, jsonResult as r, readStringParam as s, createActionGate$1 as t };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { a as resolveSlackAccount, d as resolveSlackBotToken, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, t as listEnabledSlackAccounts, u as resolveSlackAppToken } from "./accounts-ClAPP5ry.js";
|
|
2
|
+
import { n as resolveSlackGroupToolPolicy, t as resolveSlackGroupRequireMention } from "./group-policy-CyLUK6My.js";
|
|
3
|
+
import { n as setSlackRuntime } from "./runtime-Bo-KHM-F.js";
|
|
4
|
+
import { t as sendMessageSlack } from "./send-D_A9kL-C.js";
|
|
5
|
+
import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-CYLFK-Zy.js";
|
|
6
|
+
import { t as probeSlack } from "./probe-3eZf1FjI.js";
|
|
7
|
+
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-BRYqyNVJ.js";
|
|
8
|
+
import { t as resolveSlackUserAllowlist } from "./resolve-users-Bd_SdP8j.js";
|
|
9
|
+
import { t as monitorSlackProvider } from "./provider-D7uAN3Fq.js";
|
|
10
|
+
import { t as registerSlackPluginHttpRoutes } from "./plugin-routes-DtTPmga1.js";
|
|
11
|
+
import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-e2UhRsNx.js";
|
|
12
|
+
import { n as listSlackDirectoryGroupsLive, r as listSlackDirectoryPeersLive } from "./directory-live-Bf16GwDh.js";
|
|
13
|
+
import "./monitor-a97o17G6.js";
|
|
14
|
+
export { deleteSlackMessage, editSlackMessage, getSlackMemberInfo, handleSlackAction, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsLive, listSlackDirectoryPeersLive, listSlackEmojis, listSlackPins, listSlackReactions, monitorSlackProvider, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, registerSlackPluginHttpRoutes, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAppToken, resolveSlackBotToken, resolveSlackChannelAllowlist, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackUserAllowlist, sendMessageSlack, sendSlackMessage, setSlackRuntime, slackActionRuntime, unpinSlackMessage };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { r as createSlackWebClient } from "./client-CPe4GmDR.js";
|
|
2
|
+
import { t as formatSlackError } from "./errors-BYFHR24f.js";
|
|
3
|
+
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
//#region extensions/slack/src/scopes.ts
|
|
5
|
+
function collectScopes(value, into) {
|
|
6
|
+
if (!value) return;
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
for (const entry of value) if (typeof entry === "string" && entry.trim()) into.push(entry.trim());
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === "string") {
|
|
12
|
+
const raw = value.trim();
|
|
13
|
+
if (!raw) return;
|
|
14
|
+
const parts = raw.split(/[,\s]+/).map((part) => part.trim());
|
|
15
|
+
for (const part of parts) if (part) into.push(part);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!isRecord(value)) return;
|
|
19
|
+
for (const entry of Object.values(value)) if (Array.isArray(entry) || typeof entry === "string") collectScopes(entry, into);
|
|
20
|
+
}
|
|
21
|
+
function normalizeScopes(scopes) {
|
|
22
|
+
return Array.from(new Set(scopes.map((scope) => scope.trim()).filter(Boolean))).toSorted();
|
|
23
|
+
}
|
|
24
|
+
function extractScopes(payload) {
|
|
25
|
+
if (!isRecord(payload)) return [];
|
|
26
|
+
const scopes = [];
|
|
27
|
+
collectScopes(payload.scopes, scopes);
|
|
28
|
+
collectScopes(payload.scope, scopes);
|
|
29
|
+
if (isRecord(payload.response_metadata)) collectScopes(payload.response_metadata.scopes, scopes);
|
|
30
|
+
if (isRecord(payload.info)) {
|
|
31
|
+
collectScopes(payload.info.scopes, scopes);
|
|
32
|
+
collectScopes(payload.info.scope, scopes);
|
|
33
|
+
collectScopes(payload.info.user_scopes, scopes);
|
|
34
|
+
collectScopes(payload.info.bot_scopes, scopes);
|
|
35
|
+
}
|
|
36
|
+
return normalizeScopes(scopes);
|
|
37
|
+
}
|
|
38
|
+
async function callSlack(client, method) {
|
|
39
|
+
try {
|
|
40
|
+
const result = await client.apiCall(method);
|
|
41
|
+
return isRecord(result) ? result : null;
|
|
42
|
+
} catch (err) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
error: formatSlackError(err)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function fetchSlackScopes(token, timeoutMs) {
|
|
50
|
+
const client = createSlackWebClient(token, { timeout: timeoutMs });
|
|
51
|
+
const attempts = [
|
|
52
|
+
"auth.test",
|
|
53
|
+
"auth.scopes",
|
|
54
|
+
"apps.permissions.info"
|
|
55
|
+
];
|
|
56
|
+
const errors = [];
|
|
57
|
+
for (const method of attempts) {
|
|
58
|
+
const result = await callSlack(client, method);
|
|
59
|
+
const scopes = extractScopes(result);
|
|
60
|
+
if (scopes.length > 0) return {
|
|
61
|
+
ok: true,
|
|
62
|
+
scopes,
|
|
63
|
+
source: method
|
|
64
|
+
};
|
|
65
|
+
const error = isRecord(result) ? normalizeOptionalString(result.error) : void 0;
|
|
66
|
+
if (error) errors.push(`${method}: ${error}`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
error: errors.length > 0 ? errors.join(" | ") : "no scopes returned"
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { fetchSlackScopes };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { collectConditionalChannelFieldAssignments, collectSimpleChannelFieldAssignments, getChannelSurface, hasOwnProperty } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
2
|
+
//#region extensions/slack/src/secret-contract.ts
|
|
3
|
+
const secretTargetRegistryEntries = [
|
|
4
|
+
{
|
|
5
|
+
id: "channels.slack.accounts.*.appToken",
|
|
6
|
+
targetType: "channels.slack.accounts.*.appToken",
|
|
7
|
+
configFile: "openclaw.json",
|
|
8
|
+
pathPattern: "channels.slack.accounts.*.appToken",
|
|
9
|
+
secretShape: "secret_input",
|
|
10
|
+
expectedResolvedValue: "string",
|
|
11
|
+
includeInPlan: true,
|
|
12
|
+
includeInConfigure: true,
|
|
13
|
+
includeInAudit: true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "channels.slack.accounts.*.botToken",
|
|
17
|
+
targetType: "channels.slack.accounts.*.botToken",
|
|
18
|
+
configFile: "openclaw.json",
|
|
19
|
+
pathPattern: "channels.slack.accounts.*.botToken",
|
|
20
|
+
secretShape: "secret_input",
|
|
21
|
+
expectedResolvedValue: "string",
|
|
22
|
+
includeInPlan: true,
|
|
23
|
+
includeInConfigure: true,
|
|
24
|
+
includeInAudit: true
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "channels.slack.accounts.*.signingSecret",
|
|
28
|
+
targetType: "channels.slack.accounts.*.signingSecret",
|
|
29
|
+
configFile: "openclaw.json",
|
|
30
|
+
pathPattern: "channels.slack.accounts.*.signingSecret",
|
|
31
|
+
secretShape: "secret_input",
|
|
32
|
+
expectedResolvedValue: "string",
|
|
33
|
+
includeInPlan: true,
|
|
34
|
+
includeInConfigure: true,
|
|
35
|
+
includeInAudit: true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "channels.slack.accounts.*.userToken",
|
|
39
|
+
targetType: "channels.slack.accounts.*.userToken",
|
|
40
|
+
configFile: "openclaw.json",
|
|
41
|
+
pathPattern: "channels.slack.accounts.*.userToken",
|
|
42
|
+
secretShape: "secret_input",
|
|
43
|
+
expectedResolvedValue: "string",
|
|
44
|
+
includeInPlan: true,
|
|
45
|
+
includeInConfigure: true,
|
|
46
|
+
includeInAudit: true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "channels.slack.appToken",
|
|
50
|
+
targetType: "channels.slack.appToken",
|
|
51
|
+
configFile: "openclaw.json",
|
|
52
|
+
pathPattern: "channels.slack.appToken",
|
|
53
|
+
secretShape: "secret_input",
|
|
54
|
+
expectedResolvedValue: "string",
|
|
55
|
+
includeInPlan: true,
|
|
56
|
+
includeInConfigure: true,
|
|
57
|
+
includeInAudit: true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "channels.slack.botToken",
|
|
61
|
+
targetType: "channels.slack.botToken",
|
|
62
|
+
configFile: "openclaw.json",
|
|
63
|
+
pathPattern: "channels.slack.botToken",
|
|
64
|
+
secretShape: "secret_input",
|
|
65
|
+
expectedResolvedValue: "string",
|
|
66
|
+
includeInPlan: true,
|
|
67
|
+
includeInConfigure: true,
|
|
68
|
+
includeInAudit: true
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "channels.slack.signingSecret",
|
|
72
|
+
targetType: "channels.slack.signingSecret",
|
|
73
|
+
configFile: "openclaw.json",
|
|
74
|
+
pathPattern: "channels.slack.signingSecret",
|
|
75
|
+
secretShape: "secret_input",
|
|
76
|
+
expectedResolvedValue: "string",
|
|
77
|
+
includeInPlan: true,
|
|
78
|
+
includeInConfigure: true,
|
|
79
|
+
includeInAudit: true
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "channels.slack.userToken",
|
|
83
|
+
targetType: "channels.slack.userToken",
|
|
84
|
+
configFile: "openclaw.json",
|
|
85
|
+
pathPattern: "channels.slack.userToken",
|
|
86
|
+
secretShape: "secret_input",
|
|
87
|
+
expectedResolvedValue: "string",
|
|
88
|
+
includeInPlan: true,
|
|
89
|
+
includeInConfigure: true,
|
|
90
|
+
includeInAudit: true
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
function collectRuntimeConfigAssignments(params) {
|
|
94
|
+
const resolved = getChannelSurface(params.config, "slack");
|
|
95
|
+
if (!resolved) return;
|
|
96
|
+
const { channel: slack, surface } = resolved;
|
|
97
|
+
const baseMode = slack.mode === "http" || slack.mode === "socket" ? slack.mode : "socket";
|
|
98
|
+
for (const field of ["botToken", "userToken"]) collectSimpleChannelFieldAssignments({
|
|
99
|
+
channelKey: "slack",
|
|
100
|
+
field,
|
|
101
|
+
channel: slack,
|
|
102
|
+
surface,
|
|
103
|
+
defaults: params.defaults,
|
|
104
|
+
context: params.context,
|
|
105
|
+
topInactiveReason: `no enabled account inherits this top-level Slack ${field}.`,
|
|
106
|
+
accountInactiveReason: "Slack account is disabled."
|
|
107
|
+
});
|
|
108
|
+
const resolveAccountMode = (account) => account.mode === "http" || account.mode === "socket" ? account.mode : baseMode;
|
|
109
|
+
collectConditionalChannelFieldAssignments({
|
|
110
|
+
channelKey: "slack",
|
|
111
|
+
field: "appToken",
|
|
112
|
+
channel: slack,
|
|
113
|
+
surface,
|
|
114
|
+
defaults: params.defaults,
|
|
115
|
+
context: params.context,
|
|
116
|
+
topLevelActiveWithoutAccounts: baseMode !== "http",
|
|
117
|
+
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "appToken") && resolveAccountMode(account) !== "http",
|
|
118
|
+
accountActive: ({ account, enabled }) => enabled && resolveAccountMode(account) !== "http",
|
|
119
|
+
topInactiveReason: "no enabled Slack socket-mode surface inherits this top-level appToken.",
|
|
120
|
+
accountInactiveReason: "Slack account is disabled or not running in socket mode."
|
|
121
|
+
});
|
|
122
|
+
collectConditionalChannelFieldAssignments({
|
|
123
|
+
channelKey: "slack",
|
|
124
|
+
field: "signingSecret",
|
|
125
|
+
channel: slack,
|
|
126
|
+
surface,
|
|
127
|
+
defaults: params.defaults,
|
|
128
|
+
context: params.context,
|
|
129
|
+
topLevelActiveWithoutAccounts: baseMode === "http",
|
|
130
|
+
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "signingSecret") && resolveAccountMode(account) === "http",
|
|
131
|
+
accountActive: ({ account, enabled }) => enabled && resolveAccountMode(account) === "http",
|
|
132
|
+
topInactiveReason: "no enabled Slack HTTP-mode surface inherits this top-level signingSecret.",
|
|
133
|
+
accountInactiveReason: "Slack account is disabled or not running in HTTP mode."
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const channelSecrets = {
|
|
137
|
+
secretTargetRegistryEntries,
|
|
138
|
+
collectRuntimeConfigAssignments
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
export { collectRuntimeConfigAssignments as n, secretTargetRegistryEntries as r, channelSecrets as t };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
|
|
2
|
+
import { coerceNativeSetting, normalizeAllowFromList } from "openclaw/plugin-sdk/channel-policy";
|
|
3
|
+
import { readChannelAllowFromStore } from "openclaw/plugin-sdk/conversation-runtime";
|
|
4
|
+
import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "openclaw/plugin-sdk/native-command-config-runtime";
|
|
5
|
+
//#region extensions/slack/src/security-audit.ts
|
|
6
|
+
var security_audit_exports = /* @__PURE__ */ __exportAll({ collectSlackSecurityAuditFindings: () => collectSlackSecurityAuditFindings });
|
|
7
|
+
async function collectSlackSecurityAuditFindings(params) {
|
|
8
|
+
const findings = [];
|
|
9
|
+
const slackCfg = params.account.config ?? {};
|
|
10
|
+
const accountId = params.accountId?.trim() || params.account.accountId || "default";
|
|
11
|
+
if (!(slackCfg.slashCommand?.enabled === true || resolveNativeCommandsEnabled({
|
|
12
|
+
providerId: "slack",
|
|
13
|
+
providerSetting: coerceNativeSetting(slackCfg.commands?.native),
|
|
14
|
+
globalSetting: params.cfg.commands?.native
|
|
15
|
+
}) || resolveNativeSkillsEnabled({
|
|
16
|
+
providerId: "slack",
|
|
17
|
+
providerSetting: coerceNativeSetting(slackCfg.commands?.nativeSkills),
|
|
18
|
+
globalSetting: params.cfg.commands?.nativeSkills
|
|
19
|
+
}))) return findings;
|
|
20
|
+
if (!(params.cfg.commands?.useAccessGroups !== false)) {
|
|
21
|
+
findings.push({
|
|
22
|
+
checkId: "channels.slack.commands.slash.useAccessGroups_off",
|
|
23
|
+
severity: "critical",
|
|
24
|
+
title: "Slack slash commands bypass access groups",
|
|
25
|
+
detail: "Slack slash/native commands are enabled while commands.useAccessGroups=false; this can allow unrestricted /… command execution from channels/users you didn't explicitly authorize.",
|
|
26
|
+
remediation: "Set commands.useAccessGroups=true (recommended)."
|
|
27
|
+
});
|
|
28
|
+
return findings;
|
|
29
|
+
}
|
|
30
|
+
const allowFromRaw = slackCfg.allowFrom;
|
|
31
|
+
const legacyAllowFromRaw = params.account.dm?.allowFrom;
|
|
32
|
+
const allowFrom = Array.isArray(allowFromRaw) ? allowFromRaw : Array.isArray(legacyAllowFromRaw) ? legacyAllowFromRaw : [];
|
|
33
|
+
const storeAllowFrom = await readChannelAllowFromStore("slack", process.env, accountId).catch(() => []);
|
|
34
|
+
const ownerAllowFromConfigured = normalizeAllowFromList([...allowFrom, ...storeAllowFrom]).length > 0;
|
|
35
|
+
const channels = slackCfg.channels ?? {};
|
|
36
|
+
const hasAnyChannelUsersAllowlist = Object.values(channels).some((value) => {
|
|
37
|
+
if (!value || typeof value !== "object") return false;
|
|
38
|
+
const channel = value;
|
|
39
|
+
return Array.isArray(channel.users) && channel.users.length > 0;
|
|
40
|
+
});
|
|
41
|
+
if (!ownerAllowFromConfigured && !hasAnyChannelUsersAllowlist) findings.push({
|
|
42
|
+
checkId: "channels.slack.commands.slash.no_allowlists",
|
|
43
|
+
severity: "warn",
|
|
44
|
+
title: "Slack slash commands have no allowlists",
|
|
45
|
+
detail: "Slack slash/native commands are enabled, but neither an owner allowFrom list nor any channels.<id>.users allowlist is configured; /… commands will be rejected for everyone.",
|
|
46
|
+
remediation: "Approve yourself via pairing (recommended), or set channels.slack.allowFrom and/or channels.slack.channels.<id>.users."
|
|
47
|
+
});
|
|
48
|
+
return findings;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { security_audit_exports as n, collectSlackSecurityAuditFindings as t };
|