Skip to content

Commit 11d8ba9

Browse files
committed
fix: bound slack interactive button urls
1 parent 4329cee commit 11d8ba9

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Docs: https://docs.openclaw.ai
3939
- Slack/commands: keep native command argument menus on select controls for encoded choice values up to Slack's option limit and truncate fallback button labels to Slack's button-text limit, so long valid choices no longer render invalid Slack blocks. Thanks @slackapi.
4040
- Agents/Codex: flush accepted debounced steering messages before normal app-server turn cleanup, so inbound follow-ups acknowledged as queued are not dropped when the turn completes before the debounce fires. Thanks @vincentkoc.
4141
- Slack/interactive replies: keep rendered buttons and selects within Slack Block Kit value and count limits, and align command argument select values with Slack's option limit, so overlong agent-authored choices no longer make Slack reject the whole block payload. Thanks @slackapi.
42+
- Slack/interactive replies: drop overlong Block Kit button URLs while preserving valid callback values, so malformed link buttons no longer make Slack reject the whole interactive reply. Thanks @slackapi.
4243
- CLI/update: scope packaged Node compile caches by OpenClaw version and install metadata, so global installs no longer reuse stale compiled chunks after package updates. Thanks @pashpashpash.
4344
- Channels/Voice call: keep pre-auth webhook in-flight limiting active when socket remote address metadata is missing, so slow-body requests from stripped-IP proxy paths still share the fallback bucket. (#74453) Thanks @davidangularme.
4445
- Plugin SDK/testing: lazy-load TypeScript from the plugin test-contract runtime and add release checks for critical SDK contract entrypoint imports and bundle size, so published packages fail preflight before shipping ESM-incompatible or oversized contract helpers. Thanks @vincentkoc.

extensions/slack/src/blocks-render.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const SLACK_SECTION_TEXT_MAX = 3000;
1515
const SLACK_PLAIN_TEXT_MAX = 75;
1616
const SLACK_OPTION_VALUE_MAX = 75;
1717
const SLACK_BUTTON_VALUE_MAX = 2000;
18+
const SLACK_BUTTON_URL_MAX = 3000;
1819
const SLACK_STATIC_SELECT_OPTIONS_MAX = 100;
1920
const SLACK_ACTION_BLOCK_ELEMENTS_MAX = 25;
2021

@@ -72,7 +73,11 @@ export function buildSlackInteractiveBlocks(interactive?: InteractiveReply): Sla
7273
button.value && isWithinSlackLimit(button.value, SLACK_BUTTON_VALUE_MAX)
7374
? button.value
7475
: undefined;
75-
if (!value && !button.url) {
76+
const url =
77+
button.url && isWithinSlackLimit(button.url, SLACK_BUTTON_URL_MAX)
78+
? button.url
79+
: undefined;
80+
if (!value && !url) {
7681
return [];
7782
}
7883
const style = resolveSlackButtonStyle(button.style);
@@ -86,7 +91,7 @@ export function buildSlackInteractiveBlocks(interactive?: InteractiveReply): Sla
8691
emoji: true,
8792
},
8893
...(value ? { value } : {}),
89-
...(button.url ? { url: button.url } : {}),
94+
...(url ? { url } : {}),
9095
...(style ? { style } : {}),
9196
},
9297
];

extensions/slack/src/shared-interactive.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,34 @@ describe("buildSlackInteractiveBlocks", () => {
164164
expect(buttonBlock.elements?.[1]).not.toHaveProperty("value");
165165
});
166166

167+
it("drops Slack button URLs beyond Block Kit limits", () => {
168+
const validUrl = `https://example.com/${"a".repeat(2980)}`;
169+
const longUrl = `https://example.com/${"b".repeat(2981)}`;
170+
const blocks = buildSlackInteractiveBlocks({
171+
blocks: [
172+
{
173+
type: "buttons",
174+
buttons: [
175+
{ label: "Allowed", url: validUrl },
176+
{ label: "Too long", url: longUrl },
177+
{ label: "Fallback action", value: "fallback", url: longUrl },
178+
],
179+
},
180+
],
181+
});
182+
183+
const buttonBlock = blocks[0] as {
184+
elements?: Array<{ value?: string; url?: string }>;
185+
};
186+
187+
expect(validUrl).toHaveLength(3000);
188+
expect(longUrl).toHaveLength(3001);
189+
expect(buttonBlock.elements).toHaveLength(2);
190+
expect(buttonBlock.elements?.[0]?.url).toBe(validUrl);
191+
expect(buttonBlock.elements?.[1]?.value).toBe("fallback");
192+
expect(buttonBlock.elements?.[1]).not.toHaveProperty("url");
193+
});
194+
167195
it("caps Slack actions blocks at the Block Kit element limit", () => {
168196
const blocks = buildSlackInteractiveBlocks({
169197
blocks: [

0 commit comments

Comments
 (0)