fix: deliver announcements through a scoped Discord webhook (#2737)

* test: reproduce Discord webhook announcement gap

* fix: deliver ECC announcements through channel webhook

* test: cover webhook replay and least privilege

* fix: make webhook delivery durable and least privilege

* test: cover trusted receipts and cross-workflow races

* fix: serialize and authenticate announcement receipts
This commit is contained in:
Affaan Mustafa
2026-08-09 16:41:27 -04:00
committed by GitHub
parent 2d46e80e09
commit cdbb25bf9d
6 changed files with 174 additions and 13 deletions
+23
View File
@@ -6,6 +6,10 @@ async function main() {
buildDiscordPayload,
findReleaseDiscussion,
isAnnouncementDiscussion,
normalizeDiscordWebhookUrl,
discussionReceiptMarker,
findDiscussionReceipt,
discussionReceiptStatus,
releaseMarker,
} = await import('../../scripts/discord/announcement-core.mjs');
@@ -35,6 +39,25 @@ assert.equal(payload.embeds[0].url, 'https://github.com/affaan-m/ECC/discussions
assert.equal(payload.enforce_nonce, true);
assert.match(payload.nonce, /^ecc-[a-f0-9]{16}$/);
assert.equal(
normalizeDiscordWebhookUrl('https://discord.com/api/webhooks/123456789012345678/secret-token-long-enough'),
'https://discord.com/api/webhooks/123456789012345678/secret-token-long-enough?wait=true',
);
assert.throws(() => normalizeDiscordWebhookUrl('https://evil.example/api/webhooks/123/token'), /invalid Discord webhook URL/);
assert.throws(() => normalizeDiscordWebhookUrl('https://user@discord.com/api/webhooks/123456789012345678/secret-token-long-enough'), /invalid Discord webhook URL/);
assert.throws(() => normalizeDiscordWebhookUrl('https://discord.com:444/api/webhooks/123456789012345678/secret-token-long-enough'), /invalid Discord webhook URL/);
assert.throws(() => normalizeDiscordWebhookUrl('https://discord.com/api/webhooks/123456789012345678/secret-token-long-enough?leak=1'), /invalid Discord webhook URL/);
const receiptMarker = discussionReceiptMarker('affaan-m/ECC:discussion:D_kw123');
assert.match(receiptMarker, /^<!-- ecc-discord-receipt:[a-f0-9]{32} -->$/);
assert.equal(findDiscussionReceipt([
{ id: 'forged', body: `Discord delivery: complete\n${receiptMarker}`, author: { login: 'attacker' } },
{ id: 'comment-1', body: `Discord delivery: complete\n${receiptMarker}`, author: { login: 'github-actions[bot]' } },
], receiptMarker).id, 'comment-1');
assert.equal(findDiscussionReceipt([{ id: 'comment-2', body: 'unrelated' }], receiptMarker), null);
assert.equal(discussionReceiptStatus({ body: `Discord delivery: pending.\n${receiptMarker}` }), 'pending');
assert.equal(discussionReceiptStatus({ body: `Discord delivery: complete (message 1).\n${receiptMarker}` }), 'complete');
console.log('release announcement core: ok');
}