Summary
parseSlackTarget in src/slack/targets.ts blindly trusts the user-provided prefix (user:, channel:) without validating that the Slack ID format matches the declared kind. Slack IDs have well-known single-letter prefixes that indicate their type:
| ID prefix |
Slack type |
Valid target kind |
U |
User |
user |
W |
Workspace user (Enterprise Grid) |
user |
B |
Bot user |
user |
C |
Public channel |
channel |
G |
Private channel/group |
channel |
D |
DM channel |
channel |
Currently user:D0AKUMPAKMF is accepted and parsed as kind: "user", but D-prefixed IDs are DM channels. This silently misconfigures delivery targets and causes downstream failures (e.g., cron announce delivery fails with no indication of the misconfiguration).
Reproduction
- Configure a cron job with
--to "user:D0AKUMPAKMF" (DM channel ID with user: prefix)
- Job runs, agent produces output
- Announce delivery fails — no clear error about the ID/kind mismatch
- Fix: change to
--to "channel:D0AKUMPAKMF" → works immediately
Proposed Fix
In parseSlackTarget (src/slack/targets.ts), after parsing a prefixed target, validate the ID's first character against the declared kind:
const SLACK_USER_ID_PREFIXES = /^[UWB]/i;
const SLACK_CHANNEL_ID_PREFIXES = /^[CGD]/i;
// After parseTargetPrefixes returns a result:
if (prefixedTarget) {
const idChar = prefixedTarget.id[0]?.toUpperCase();
if (prefixedTarget.kind === "user" && SLACK_CHANNEL_ID_PREFIXES.test(idChar)) {
throw new Error(
`Slack ID "${prefixedTarget.id}" looks like a ${idChar === "D" ? "DM channel" : "channel"} (${idChar}-prefix), ` +
`but was specified as user:. Use channel:${prefixedTarget.id} instead.`
);
}
if (prefixedTarget.kind === "channel" && SLACK_USER_ID_PREFIXES.test(idChar)) {
throw new Error(
`Slack ID "${prefixedTarget.id}" looks like a user (${idChar}-prefix), ` +
`but was specified as channel:. Use user:${prefixedTarget.id} instead.`
);
}
return prefixedTarget;
}
Scope
- Only Slack — Discord uses numeric snowflake IDs with no type-prefix convention
- Validation at parse time in
parseSlackTarget, not in the generic channels/targets.ts
- Error with a helpful message (suggest the correct prefix), don't silently auto-correct
Discovered While
Debugging cron announce delivery failure (#2083). The root issue was auth (#2083), but after fixing auth, delivery still failed because the Slack target used user:D... instead of channel:D....
Summary
parseSlackTargetinsrc/slack/targets.tsblindly trusts the user-provided prefix (user:,channel:) without validating that the Slack ID format matches the declared kind. Slack IDs have well-known single-letter prefixes that indicate their type:UuserWuserBuserCchannelGchannelDchannelCurrently
user:D0AKUMPAKMFis accepted and parsed askind: "user", butD-prefixed IDs are DM channels. This silently misconfigures delivery targets and causes downstream failures (e.g., cron announce delivery fails with no indication of the misconfiguration).Reproduction
--to "user:D0AKUMPAKMF"(DM channel ID withuser:prefix)--to "channel:D0AKUMPAKMF"→ works immediatelyProposed Fix
In
parseSlackTarget(src/slack/targets.ts), after parsing a prefixed target, validate the ID's first character against the declared kind:Scope
parseSlackTarget, not in the genericchannels/targets.tsDiscovered While
Debugging cron announce delivery failure (#2083). The root issue was auth (#2083), but after fixing auth, delivery still failed because the Slack target used
user:D...instead ofchannel:D....