Compare commits

...

2 Commits

Author SHA1 Message Date
Shadow
288875af45 fix: note Discord guild allowlist resolution (#12326) (thanks @headswim) 2026-02-13 11:01:02 -06:00
headswim
5a627d6c12 Discord: fix bare guild ID misrouted as channel ID in parser
The channel allowlist parser matches bare numeric strings as channel IDs
before checking for guild IDs, causing guild snowflakes to hit Discord's
/channels/ endpoint (404). Prefix guild-only entries with 'guild:' so the
parser routes them to the correct guild resolution path.

Fixes both the monitor provider and onboarding wizard call sites.
Adds regression tests.
2026-02-13 11:00:08 -06:00
2 changed files with 59 additions and 0 deletions

View File

@@ -40,6 +40,7 @@ Docs: https://docs.openclaw.ai
- Sessions/Agents: pass `agentId` when resolving existing transcript paths in reply runs so non-default agents and heartbeat/chat handlers no longer fail with `Session file path must be within sessions directory`. (#15141) Thanks @Goldenmonstew.
- Sessions/Agents: pass `agentId` through status and usage transcript-resolution paths (auto-reply, gateway usage APIs, and session cost/log loaders) so non-default agents can resolve absolute session files without path-validation failures. (#15103) Thanks @jalehman.
- Signal/Install: auto-install `signal-cli` via Homebrew on non-x64 Linux architectures, avoiding x86_64 native binary `Exec format error` failures on arm64/arm hosts. (#15443) Thanks @jogvan-k.
- Discord: avoid misrouting numeric guild allowlist entries to `/channels/<guildId>` by prefixing guild-only inputs with `guild:` during resolution. (#12326) Thanks @headswim.
- Web tools/web_fetch: prefer `text/markdown` responses for Cloudflare Markdown for Agents, add `cf-markdown` extraction for markdown bodies, and redact fetched URLs in `x-markdown-tokens` debug logs to avoid leaking raw paths/query params. (#15376) Thanks @Yaxuan42.
- Config: keep legacy audio transcription migration strict by rejecting non-string/unsafe command tokens while still migrating valid custom script executables. (#5042) Thanks @shayan919293.

View File

@@ -52,4 +52,62 @@ describe("resolveDiscordChannelAllowlist", () => {
expect(res[0]?.guildId).toBe("g1");
expect(res[0]?.channelId).toBe("123");
});
it("resolves guild: prefixed id as guild (not channel)", async () => {
const fetcher = async (url: string) => {
if (url.endsWith("/users/@me/guilds")) {
return jsonResponse([{ id: "111222333444555666", name: "Guild One" }]);
}
// Should never be called — if it is, the ID was misrouted as a channel
if (url.includes("/channels/")) {
throw new Error("guild id was incorrectly routed to /channels/");
}
return new Response("not found", { status: 404 });
};
const res = await resolveDiscordChannelAllowlist({
token: "test",
entries: ["guild:111222333444555666"],
fetcher,
});
expect(res[0]?.resolved).toBe(true);
expect(res[0]?.guildId).toBe("111222333444555666");
expect(res[0]?.channelId).toBeUndefined();
});
it("bare numeric guild id is misrouted as channel id (regression)", async () => {
// Demonstrates why provider.ts must prefix guild-only entries with "guild:"
// In reality, Discord returns 404 when a guild ID is sent to /channels/<guildId>,
// which causes fetchDiscord to throw and the entire resolver to crash.
const fetcher = async (url: string) => {
if (url.endsWith("/users/@me/guilds")) {
return jsonResponse([{ id: "999", name: "My Server" }]);
}
// Guild ID hitting /channels/ returns 404 — just like real Discord
if (url.includes("/channels/")) {
return new Response(JSON.stringify({ message: "Unknown Channel" }), { status: 404 });
}
return new Response("not found", { status: 404 });
};
// Without the guild: prefix, a bare numeric string hits /channels/999 → 404 → throws
await expect(
resolveDiscordChannelAllowlist({
token: "test",
entries: ["999"],
fetcher,
}),
).rejects.toThrow(/404/);
// With the guild: prefix, it correctly resolves as a guild (never hits /channels/)
const res2 = await resolveDiscordChannelAllowlist({
token: "test",
entries: ["guild:999"],
fetcher,
});
expect(res2[0]?.resolved).toBe(true);
expect(res2[0]?.guildId).toBe("999");
expect(res2[0]?.channelId).toBeUndefined();
});
});