Skip to content

httprpc: incomplete rTorrent 0.16.9 trust fix — default case still blocks load.start #3046

@de666

Description

@de666

Please complete the following tasks.

  • Web browser cache cleared
  • Link provided to install script if applicable
  • Not using broken rtinst install script
  • Web browser, ruTorrent, PHP and OS version provided

Tell us about your environment

https://github.com/crazy-max/docker-rtorrent-rutorrent
Browser not relevant

Tell us how you installed ruTorrent

https://github.com/crazy-max/docker-rtorrent-rutorrent

Describe the bug

Description

The v5.3.0 fix for rTorrent 0.16.9 compatibility (commit 87315d6) is incomplete.

External clients that use plugins/httprpc/action.php as their RPC endpoint (Prowlarr, Sonarr,
Radarr, Transdrone, NZB360, etc.) still receive the following error when trying to add torrents:

rTorrent returned error code 0: Command "load.start" is not allowed for untrusted connections

Steps to reproduce

  1. configure and run https://github.com/crazy-max/docker-rtorrent-rutorrent
  2. configure and run prowlarr
  3. configure rutorrent as a client inside prowlarr through httprcp
  4. try to add any torrent from prowlarr

Expected behavior

Torrent is added correctly

Additional context

Background: rTorrent 0.16.9 trust model

rTorrent 0.16.9 introduced a trusted/untrusted XMLRPC connection security model based on the
UNTRUSTED_CONNECTION SCGI header flag. When set to 1, rTorrent restricts the connection to
a whitelist of allowed commands, blocking anything not explicitly listed — including load.start,
load.raw.start, and others commonly used by external clients.

The flag is set in php/xmlrpc.php (line ~109):

$reqheader = "CONTENT_LENGTH\x0".$contentlength."\x0"."CONTENT_TYPE\x0"."text/xml\x0"
           . "SCGI\x0"."1\x0UNTRUSTED_CONNECTION\x0".($trusted ? "0" : "1")."\x0";

The $trusted parameter propagates from rXMLRPCRequest::send($data, $trusted),
rXMLRPCRequest::run($trusted), and rXMLRPCRequest::success($trusted).

What the v5.3.0 fix addressed

The fix correctly changed all ->success(false) calls to ->success(true) throughout
action.php, covering all the named modes (list, start, stop, pause, remove, etc.)
used by the ruTorrent UI itself.

What was missed

There is one remaining call that still passes false — the default case, which handles
raw XMLRPC pass-through:

default:
{
    if(isset($HTTP_RAW_POST_DATA))
    {
        $result = rXMLRPCRequest::send($HTTP_RAW_POST_DATA, false); // ← still untrusted

This is exactly the code path used by external clients like Prowlarr, Sonarr, and Radarr.
These clients do not use the named modes — they send raw XMLRPC payloads directly, which are
handled exclusively by this default case. As a result, commands like load.start are still
rejected by rTorrent 0.16.9 even after upgrading to ruTorrent v5.3.0.

How I found this

The error first appeared when Prowlarr (configured to use plugins/httprpc/action.php as the
RPC endpoint) stopped being able to add torrents after upgrading to rTorrent 0.16.9.

Tracing the request path:

  • Prowlarr sends a raw XMLRPC payload to plugins/httprpc/action.php
  • Since the payload does not match any named $mode, it falls through to the default case
  • rXMLRPCRequest::send($HTTP_RAW_POST_DATA, false) is called, setting UNTRUSTED_CONNECTION: 1
  • rTorrent 0.16.9 rejects load.start as it is not on the untrusted whitelist

The named modes (start, stop, etc.) work correctly after the v5.3.0 fix because they all
use ->success(true). Only the raw pass-through path remains broken.

Why marking this as trusted is correct and safe

The default case is only reachable by clients that have already passed through nginx
authentication (HTTP basic auth or similar) configured by the image. The trusted/untrusted
distinction in rTorrent 0.16.9 is designed to separate unauthenticated external network
connections from trusted local ones — not to filter commands within an already-authenticated
PHP proxy. Marking this connection as untrusted is therefore inconsistent with how all other
modes in the same file are treated.

Fix

One-line change in plugins/httprpc/action.php:

- $result = rXMLRPCRequest::send($HTTP_RAW_POST_DATA, false);
+ $result = rXMLRPCRequest::send($HTTP_RAW_POST_DATA, true);

Affected clients

Any client configured to use /plugins/httprpc/action.php as the RPC endpoint and sending
raw XMLRPC payloads, including:

  • Prowlarr
  • Sonarr (with rTorrent integration)
  • Radarr (with rTorrent integration)
  • Transdrone / Transdroid
  • NZB360
  • Any other *arr or automation tool using raw XMLRPC

Workaround (until fixed)

Add the following to a custom init script (mapped into /etc/cont-init.d/ for
crazy-max/docker-rtorrent-rutorrent, or equivalent for other setups):

ACTION_PHP="/var/www/rutorrent/plugins/httprpc/action.php"

if grep -qF 'success(false)' "$ACTION_PHP" || grep -qF 'send($HTTP_RAW_POST_DATA,false)' "$ACTION_PHP"; then
    sed -i 's/success(false)/success(true)/g' "$ACTION_PHP"
    sed -i 's/send(\$HTTP_RAW_POST_DATA,false)/send(\$HTTP_RAW_POST_DATA,true)/g' "$ACTION_PHP"
    echo "httprpc action.php patched"
else
    echo "httprpc action.php already patched, skipping"
fi

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions