logo

Port 9091 – Transmission (BitTorrent Web UI & RPC Interface)

Service:

transmission-daemon (Transmission RPC / Web UI); also Prometheus PushgatewayOpenfire admin

Protocol:

TCP

Port:

9091

Used for:

Hosting the Transmission BitTorrent client's web UI and JSON-RPC remote-control interface, and also seen with Prometheus Pushgateway and other web management consoles

Port 9091 is the default port for the Transmission BitTorrent client’s web UI and JSON-RPC interface — the daemon’s remote-control API. When you run transmission-daemon (the headless flavour of Transmission used on NAS boxes, seedboxes, and Linux servers), it opens an HTTP listener on 9091 that serves a browser client at /transmission/web/ and a JSON-RPC endpoint at /transmission/rpc. That RPC is the whole daemon in a box: it can add and remove torrents, read the download list, change settings, and — importantly — set the download directory and a “run this script when a torrent finishes” hook. A handful of other products also land on 9091 (Prometheus Pushgateway uses it by default, Openfire’s HTTPS admin console defaults to 9091, and some SOCKS/proxy tools pick it), so the first job on an open 9091 is to confirm which it is — but far and away the most common and most dangerous occupant is an exposed Transmission RPC.

Why It’s Open

The dominant use of port 9091 is the Transmission remote-control API. Transmission ships as a client/server pair: transmission-daemon runs headless in the background and does the actual downloading, while the UI you interact with — the bundled web client, the desktop apps, or third-party remotes like Transmission Remote GUI — is just a client that drives the daemon over JSON-RPC on 9091. People deliberately expose 9091 so they can manage downloads from a browser or phone while the daemon runs on a NAS, a home server, or a rented seedbox. On appliances (Synology, QNAP, OpenWrt/Entware, various “torrent box” images) the daemon is frequently enabled by default, and the port often gets forwarded through the router so it’s reachable from outside the LAN.

Port 9091 is also a web-management default for other software, which is why fingerprinting matters:

  • Prometheus Pushgateway listens on 9091 by default, exposing /metrics and a push API for batch/ephemeral jobs — a monitoring component, not a torrent client. (Prometheus itself lives on port 9090.)
  • Openfire (the XMPP server) serves its secure admin console on 9091 (with the plain console on 9090).
  • Assorted SOCKS/HTTP proxies and internal dashboards grab 9091 when the usual web ports are taken.

So an open 9091 usually means Transmission’s RPC, but it can be a Pushgateway, an Openfire admin panel, or a custom web tool — identify it before you test it.

Common Risks

  • Exposed RPC with no or weak authentication. Transmission’s RPC does not require a password by default — rpc-authentication-required is off out of the box. Its only default protection is rpc-whitelist (limited to 127.0.0.1), which stops off-host requests but is trivially disabled by users who want remote access. An RPC reachable over the network with auth off means anyone who can hit 9091 controls the daemon completely.
  • Remote code execution via script-torrent-done. The RPC can set script-torrent-done-enabled plus script-torrent-done-filename (a command to run when a download completes) and set the download-dir. Combine “write an attacker-controlled file to a chosen path” with “run a chosen script on completion” and you have arbitrary command execution as the user running the daemon. This is the primitive behind the famous 2018 attack (see CVEs).
  • DNS rebinding / CSRF against the JSON-RPC. Even a daemon bound to localhost was reachable through a victim’s browser via DNS rebinding, because the RPC relied on a readable header for access control rather than real origin checks (CVE-2018-5702). Any web page the user visited could then drive the local RPC.
  • Exposed downloads and download history. The RPC and web UI happily list every torrent, file name, and download path — enough to reveal what a target is downloading and where it lands on disk.
  • Default / weak credentials. Where users do turn auth on, they often pick weak or reused passwords (transmission:transmission, admin:admin), and Transmission’s RPC has no lockout or rate limiting to slow a brute-force.
  • Wrong-service surprises. If 9091 is actually a Prometheus Pushgateway or an Openfire console, it carries that product’s exposure instead — leaked metrics/topology from Pushgateway, or an admin panel on Openfire.

Want to save time on reporting?

Let PentestPad generate, track, and export your reports - automatically.

logo-cta

Enumeration & Testing

The whole game on 9091 is confirming it’s Transmission’s RPC and then checking whether it’s locked down. Transmission has a giveaway fingerprint: an unadorned request to /transmission/rpc is answered with HTTP 409 Conflict and an X-Transmission-Session-Id header.

Detect the service and version

Terminal window
nmap -sV -p 9091 <target>
nmap -sV -p 9091 --script=http-title,http-headers <target>

Fingerprint the RPC (the 409 tell)

Terminal window
curl -i http://<target>:9091/transmission/rpc

A 409 Conflict with an X-Transmission-Session-Id: header confirms Transmission. That header is CSRF/rebinding protection — you must echo it back on the real request.

Load the web client

Terminal window
curl -s http://<target>:9091/transmission/web/ | head

If the Transmission web UI renders without a login prompt, the RPC behind it is unauthenticated.

Drive the RPC (read config and version)

Terminal window
# Grab the session id, then call session-get
SID=$(curl -s -D - http://<target>:9091/transmission/rpc -o /dev/null \
| grep -Fi X-Transmission-Session-Id | tr -d '\r' | awk '{print $2}')
curl -s http://<target>:9091/transmission/rpc \
-H "X-Transmission-Session-Id: $SID" \
-d '{"method":"session-get"}'

A JSON reply (rather than a 401 Unauthorized) means the RPC is answering without credentials. The response includes the Transmission version, the download-dir, and whether script-torrent-done-enabled is set — all of which decide how bad the exposure is. If you get a 401, test for weak auth:

Terminal window
curl -s -u transmission:transmission http://<target>:9091/transmission/rpc \
-H "X-Transmission-Session-Id: $SID" -d '{"method":"session-get"}'

Rule out a Prometheus Pushgateway on 9091

Terminal window
curl -s http://<target>:9091/metrics | head

Prometheus exposition text (# HELP / # TYPE lines) means it’s a Pushgateway, not Transmission — pivot to metrics/topology exposure instead.

Record every open port 9091, the exact service and version you fingerprint, and whether the RPC answered without auth, so the evidence lands in the pentest report instead of a scratch terminal you’ll lose.

What to Look For

Checkpoint What it means
409 + X-Transmission-Session-Id header on /transmission/rpc Confirms a Transmission RPC daemon — the canonical fingerprint
/transmission/web/ loads without a login Web UI exposed and the RPC behind it needs no credentials
session-get returns JSON (no 401) RPC is unauthenticated — anyone reachable can fully control the daemon
script-torrent-done-enabled set or settable Command-execution primitive: the daemon runs a script on torrent completion
Transmission version ≤ 2.92 Vulnerable to CVE-2018-5702 DNS-rebinding-to-RCE
rpc-whitelist-enabled: false or a 0.0.0.0 bind RPC deliberately opened beyond localhost — reachable off-host
/metrics returns Prometheus text It’s a Pushgateway, not Transmission — retest for metrics exposure
Default creds (transmission:transmission) accepted Trivial auth bypass; no lockout to slow brute-force

Known CVEs and Exploits

Port 9091 has no generic CVE — the risk is the RPC’s design: an unauthenticated remote-control API that can write files and run scripts. The one headline network CVE, and the reason this port is notorious, is the DNS-rebinding flaw:

  • CVE-2018-5702 — Transmission through 2.92 relied on the X-Transmission-Session-Id header for access control on /transmission/rpc. Because that header is not “forbidden” for the browser Fetch API, a remote web page could read and set it, so a DNS-rebinding attack turned a localhost-only RPC into remote command execution. Tavis Ormandy of Google Project Zero reported it in late 2017: a malicious site with a short-TTL domain first serves JavaScript, then rebinds the domain to 127.0.0.1; the victim’s browser now talks to the local daemon as same-origin, reads the session id from the 409 response, and issues RPC calls to set script-torrent-done + download-dir and add a torrent — running attacker code when it finishes. CVSS 3.0 8.8 (High). Public proof-of-concept: Exploit-DB 43665 (Google Security Research). Fixed in Transmission 2.93, which validates the request’s Host header to defeat rebinding.

Important caveat: the 2.93 fix only closes the browser-driven DNS-rebinding path. It does not make an exposed RPC safe. A patched daemon that is reachable over the network with rpc-authentication-required off is still fully controllable by anyone who can reach 9091 directly — including the same script-torrent-done route to code execution. Treat “RPC reachable + no auth” as the real finding whether or not the version is patched.

The peer-facing side of Transmission has separately had memory-corruption bugs (for example an integer overflow in tr_bitfieldEnsureNthBitAlloced before 2.84, and a libutp overflow before 2.74), but those are reached through the BitTorrent peer protocol, not the 9091 RPC/web port, so they don’t belong to this page.

Removed from the previous version of this page: three CVEs that were mislabeled and belong to entirely different software. CVE-2020-15157 is a containerd registry-credential leak (not a “Transmission Web UI CSRF”). CVE-2023-2721 is a Google Chrome use-after-free (not a “Grafana/Prometheus information disclosure”). CVE-2018-5703 is a Linux kernel IPv6 TCP out-of-bounds write (not a “Transmission RPC auth bypass”). None affect any service on port 9091, and all three have been deleted. Always confirm a CVE’s product on its NVD record before trusting a stub’s label.

Mitigation

  • Confirm what’s on 9091 first. Fingerprint it (the 409 + X-Transmission-Session-Id tell for Transmission, /metrics for a Pushgateway) and harden the specific service, not the port number.
  • Never expose the RPC directly to untrusted networks. Keep transmission-daemon bound to 127.0.0.1 and reach it over a VPN or an SSH tunnel. If it must be remote, put it behind a reverse proxy that terminates TLS on 443 and enforces authentication.
  • Turn on RPC authentication. Set rpc-authentication-required: true with a strong, unique rpc-username/rpc-password — never transmission:transmission or another default.
  • Keep and tighten the whitelist. Leave rpc-whitelist-enabled: true and list only the specific admin hosts; don’t “fix” remote access by disabling the whitelist.
  • Patch to a current Transmission (≥ 2.93, ideally the latest) so the DNS-rebinding path is closed, and disable script-torrent-done unless you genuinely need it.
  • Run the daemon unprivileged. Use a dedicated low-privilege account and confine the download directory so a script-torrent-done abuse can’t reach sensitive files or escalate.
  • Firewall TCP/9091 to admin sources only, and audit routers and cloud security groups for an accidental 0.0.0.0:9091 forward. If nothing needs it, stop the daemon and rescan to confirm the port is closed. For alternate web/proxy tools that also squat here, apply the same discipline you would to port 8080.

Real-World Example

The canonical incident is Tavis Ormandy’s 2018 Project Zero attack on Transmission (CVE-2018-5702). Ormandy noticed that Transmission’s RPC guarded itself with the X-Transmission-Session-Id header — a defense that assumes only a trusted client can read and echo it. But a browser can read that header for a request to a domain it “owns,” and DNS rebinding lets an attacker own a domain that points at the victim’s own 127.0.0.1. His proof-of-concept served a page from a short-TTL domain, waited for the DNS entry to flip to localhost, then used XMLHttpRequest to hit http://<attacker-domain>:9091/transmission/rpc, pull the session id out of the 409 response, and issue RPC calls that set script-torrent-done-filename to a script and pointed the download directory at it — so simply visiting a web page while transmission-daemon ran locally could execute code on the machine. It’s the definitive lesson for port 9091: a remote-control RPC that can write files and launch scripts is a code-execution engine, and “it only listens on localhost” is not a security boundary once a browser is in the loop.

FAQ

What is port 9091 used for?

Port 9091 is the default port for the Transmission BitTorrent client’s web UI and JSON-RPC remote-control interface — served by transmission-daemon at /transmission/web/ and /transmission/rpc. It lets you manage torrent downloads from a browser or a remote app. The same port is also the default for Prometheus Pushgateway and Openfire’s HTTPS admin console, so an open 9091 should be fingerprinted before it’s assumed to be Transmission.

Why is port 9091 open on my computer or router?

Most often because transmission-daemon is running — commonly on a NAS, seedbox, or home server — and someone enabled its remote UI (and possibly port-forwarded it through the router) to manage downloads from elsewhere. It can also be a Prometheus Pushgateway or an Openfire admin panel. If you didn’t set up any of those, fingerprint the service before trusting it.

Is an exposed Transmission RPC dangerous?

Yes. Transmission’s RPC requires no password by default, and it can set a “run this script when a torrent finishes” hook plus the download directory — which together allow arbitrary command execution on the host. An RPC reachable over the network with authentication off effectively hands remote users control of the account running the daemon, so it should never face an untrusted network unprotected.

What was the Transmission DNS-rebinding attack (CVE-2018-5702)?

It was a 2018 flaw, found by Google Project Zero, where Transmission (≤ 2.92) relied on a browser-readable header instead of real origin checks. Using DNS rebinding, a malicious web page could make the victim’s browser talk to the local RPC as if same-origin, then set script-torrent-done and the download directory to run attacker code — turning a localhost-only daemon into remote code execution just from visiting a page. Transmission 2.93 fixed it by validating the Host header.

Does Transmission need a password by default?

No. Out of the box rpc-authentication-required is false; the only default protection is rpc-whitelist, which limits the RPC to 127.0.0.1. Users who want remote access often disable the whitelist without turning on authentication, which is exactly how these daemons end up wide open on the internet. Always set a strong rpc-username/rpc-password.

How do I secure or close port 9091?

Keep the daemon bound to localhost and reach it over a VPN or SSH tunnel; if it must be remote, front it with a reverse proxy that enforces TLS and authentication. Enable rpc-authentication-required with strong credentials, keep the whitelist tight, patch Transmission to ≥ 2.93, disable script-torrent-done unless needed, run the daemon unprivileged, and firewall TCP/9091 to admin hosts. If nothing needs it, stop the service and rescan to confirm the port is closed.

TL;DR

  • Service: Transmission BitTorrent web UI + JSON-RPC (transmission-daemon on /transmission/rpc and /transmission/web/); also Prometheus Pushgateway and Openfire’s admin console on the same port
  • Default port: 9091/TCP
  • Biggest risk: an exposed RPC with no/weak auth — it can set script-torrent-done and the download directory, giving remote code execution (the 2018 Project Zero DNS-rebinding-to-RCE, CVE-2018-5702, is the classic case; patching doesn’t help if the RPC is still reachable unauthenticated)
  • Mitigation: bind to localhost / VPN, require RPC auth with strong creds, keep the whitelist tight, patch to ≥ 2.93, disable the completion-script hook, run unprivileged, and firewall 9091 to admin hosts