dcc-chat: cap CTCP body length used in dynamic signal name

The body of a CTCP message received over an established DCC CHAT
connection is concatenated into a dynamic signal name and emitted via
signal_emit. The first whitespace-separated token becomes the CTCP
command and the remainder is delivered to any matching handler as the
second argument, including loaded perl scripts.

While irssi itself does not crash on unknown signal names (the signal
system interns them and signal_emit returns FALSE for no-match), the
unbounded body length widens the attack surface for any perl script
that operates unsafely on the CTCP argument.

A 256-byte cap on the body that is concatenated into the signal name
limits the attack surface and aligns with the convention used for
CTCP-over-IRC handling.
This commit is contained in:
Devon Kirk 2026-07-01 17:15:57 -04:00
commit 283d846787

View file

@ -730,6 +730,16 @@ static void dcc_chat_msg(CHAT_DCC_REC *dcc, const char *msg)
if (*msg != 1)
return;
/* Cap the CTCP body length that is concatenated into the signal name. The
* body comes from a remote peer on an established DCC CHAT connection
* and is passed as the second argument to any matching signal handler
* (including loaded perl scripts). A modest cap limits the attack surface
* for the dynamic-signal-name dispatch and aligns with the convention
* used for CTCP-over-IRC. */
if (strlen(msg+1) > 256) {
return;
}
/* get ctcp command, remove \001 chars */
event = g_strconcat(reply ? "dcc reply " : "dcc ctcp ", msg+1, NULL);
if (event[strlen(event)-1] == 1) event[strlen(event)-1] = '\0';