Forum teuk.org

Partyline hardening and new commands (May 2026)

in Mediabot Β· started by TeuK Β· 1w ago

TeuK Β· 1w ago

Mediabot v3 β€” Partyline hardening and new commands (May 2026)

Context

Deep audit of Mediabot::Partyline and Mediabot::DCC on snapshot 20260502. Six bugs were found and disarmed, six improvements were conjured. This is the most substantial single-pass improvement to the Partyline since it was written.


Bug fixes

B1 β€” DCC CHAT passwords were logged in clear text

The on_read handler for DCC CHAT sessions was masking passwords only when auth_stage was dcc_pass β€” a stage that no longer exists since the DCC flow was unified with the standard nick/password flow. As a result, the password typed during a DCC CHAT login was written verbatim to the bot log at DEBUG3 level. Fixed by checking for pass, the correct active stage.

This is a real security issue: anyone with access to the log files could recover Mediabot passwords for any DCC session opened since the regression was introduced.

B2 β€” Rate limiting fired during authentication

The rate limiter (max 10 lines per 5 seconds) was applied unconditionally at the top of _handle_line, before checking whether the session was authenticated. This meant a user typing their nickname slowly, or a client that sends negotiation lines, could exhaust the rate budget and be blocked before ever completing the login flow. Worse, the brute-force login_failures counter (max 5 attempts) was already protecting the auth phase β€” the rate limiter was redundant and harmful there. The rate limiter now only fires for authenticated sessions.

B3 β€” Error message lost on brute-force disconnect

When a session exceeded 5 failed login attempts, the code was calling $stream->close_now immediately after $stream->write(...). On a fast network this is usually fine, but close_now drops the socket without waiting for the write buffer to flush. On a slow link or under load, the β€œToo many authentication failures. Disconnecting.” message was silently discarded. Changed to close_when_empty, which closes the connection only after the write buffer is drained.

B4 β€” Dead imports bloating Partyline

use POSIX qw(setsid) and use File::Basename qw(dirname) were present in Partyline.pm as leftovers from the module split. Neither setsid nor dirname is called anywhere in the file. Removed.

B5 β€” DCC CHAT offers routed through botPrivmsg side effects

offer_dcc_chat and accept_dcc_chat_passive were sending the CTCP \x01DCC CHAT chat...\x01 payload via botPrivmsg. For nick targets (not channels), botPrivmsg skips the NoColors filter but still runs AntiFlood checks, Badword filtering, and writes a [LIVE] log line β€” all of which are meaningless and potentially harmful for a raw CTCP payload. The DCC offer is now sent via $bot->{irc}->send_message('PRIVMSG', ...) directly, bypassing all those layers entirely.

B6 β€” Partyline broadcast showed unknown@unknown on disconnect

In both the telnet and DCC CHAT on_closed handlers, _display_nick was called after _close_session. Since _close_session deletes $self->{users}{$id}, _display_nick was reading from an already-deleted hash entry and falling back to unknown@unknown. The display string is now captured before _close_session is called, so disconnect announcements always show the real handle and host.


New commands and improvements

A1 β€” .ping keepalive command

You must be logged in to reply.