CVE-2026-88046: rclone: source object names can escape the configured root on upload

Published Sep 10, 2026
·
Updated

Summary

Multiple backends, when given a specially crafted object to copy, can escape the backend confinement.

| Backend | Keep/Close | Per-backend severity | |---|---|---| | sftp | Medium | Real filesystem escape, fires under default encoding. | | smb | Low-Medium | Escapes to a different SMB share the credential can reach. | | ftp | Low | Real, leading-.. overshoot PoC is partly neutralized by encoding; escape bounded to at/below the login base. | | webdav | Low | Server-side ACLs are the real boundary. | | b2 | Low | Same-account sibling bucket crossing on a flat keyspace. | | swift | Low | Same, container. | | qingstor | Low | Same. | | oracleobjectstorage | Low | Same. | | internetarchive | Low | IA items are owner-writable only; confined to user's own items. | | storj | Low | Can retarget a different bucket in the same access grant. | | filelu | Low | Confined to the user's own account. | | shade | Low | Confined to the user's own drive. | | sia | Low | siad API password already grants full-daemon access. |

Root cause

rclone core does not sanitize .. in a source object's Remote() - verified: nothing in fs/march, fs/sync, fs/list, or fs/operations rejects .. segments before the name reaches the destination backend's Put/Update/Mkdir. Confinement is therefore each backend's responsibility, and these backends join root + remote without a check.

This divides into two classes:

- Bucket based backends - bucket.Split(path.Join(f.root, rootRelativePath)): - backend/b2/b2.go:404, backend/swift/swift.go:464, backend/qingstor/qingstor.go:198, backend/oracleobjectstorage/oracleobjectstorage.go:245, backend/internetarchive/internetarchive.go:1016, backend/smb/smb.go:885, backend/storj/fs.go:289. - path.Join collapses .. on the standard (ASCII) form before encoding is applied (e.g. FromStandardPath(path.Join(...)) at backend/b2/b2.go:1641), so EncodeDot never gets the chance to neutralize the ... - lib/bucket.Join does not clean paths (keeps .. as a literal key segment); path.Join does. backend/s3, backend/azureblob, backend/googlecloudstorage already use bucket.Join and are therefore not affected.

- Path based backends - path.Join(root, remote) onto a real path: - sftp: remotePath = path.Join(f.absRoot, f.opt.Enc.FromStandardPath(remote)) (backend/sftp/sftp.go:2497). Default encoding is encoder.Display (== Standard), and FromStandardPath short-circuits to a pass-through in that mode, so .. survives; f.absRoot is absolute, so path.Join("/home/user/root", "../../../../etc/passwd") -> /etc/passwd. - webdav: filePath at backend/webdav/webdav.go:426-432. - ftp: path.Join(f.root, remote) at ~14 sites (e.g. backend/ftp/ftp.go:1247). - filelu, shade, sia: analogous joins.

Precondition that limits reachability

For any of these to fire, a source must hand rclone a Remote() containing raw ... That is only possible when:

1. the source is a flat-keyspace object store (not a filesystem - a local/sftp/smb source cannot represent ../../x as one directory entry), and 2. the offending key was written with native, non-rclone tooling - rclone's own writer applies EncodeDot and rewrites a .. segment to fullwidth .., so you cannot create such a key through rclone.

rclone's source-side listing does pass a natively-planted raw .. key through unchanged (verified for b2: remote := file.Name[len(prefix):] after ToStandardPath, backend/b2/b2.go:858,867). The reports never establish this precondition; it is the same omission across every member of the class.

Example attack

bash Step 1 - attacker, using NATIVE S3 tooling (NOT rclone) on a source the victim ingests from: aws s3api put-object --bucket shared-drop --key '../../victim-backups/pwned.txt' --body evil.txt

Step 2 - victim's ordinary ingest: rclone copy s3-drop:shared-drop b2:victim-uploads/incoming path.Join("victim-uploads/incoming", "../../victim-backups/pwned.txt") = "victim-backups/pwned.txt" -> lands in the victim's victim-backups bucket instead of under incoming/

The blast radius is the victim's own account (a bucket/share/path the configured credential already reaches) - integrity misdirection, not a cross-tenant or confidentiality breach. sftp/smb are the exception in reach (server filesystem / other share), still bounded by the login's own permissions.

Precedent

This is the same class as the already-fixed local backend advisory https://github.com/rclone/rclone/security/advisories/GHSA-7p4m-qxvv-g567, which added (Fs).localPath returning errPathEscapes for names resolving outside the root (backend/local/local.go:819-826). That fix was justified because the destination was the operator's own OS filesystem; the same reasoning extends (at lower severity) to sftp/smb.

Other sources

rclone is a command-line program to sync files and directories to and from different cloud storage providers. Prior to 1.75.1, rclone core does not reject parent-directory segments in source Object.Remote() values before fs/list, fs/walk, fs/sync, and fs/operations pass those values to destination backends. A flat-keyspace source object store populated with native non-rclone tooling can contain a raw .. key segment, and affected b2, swift, qingstor, oracleobjectstorage, internetarchive, smb, storj, sftp, webdav, ftp, filelu, shade, and sia destinations use path.Join(root, remote) before EncodeDot can neutralize the segment. A copy or upload can therefore escape the configured root into another bucket, share, or path reachable by the victim credential, with sftp and smb potentially reaching other filesystem or share locations under the same login authority. This issue is fixed in version 1.75.1.

— MITRE

Affected Software

2 affected componentsFixes available
Rclone Rclone<1.75.1
go/github.com/rclone/rclone<1.75.1
1.75.1

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/github.com/rclone/rclone to a version that resolves this vulnerability.

    Fixed in 1.75.1
  2. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Fixed in 1.75.1Patch GHSA-7p4m-qxvv-g567

Event History

Sep 10, 2026
CVE Published
via MITRE·04:14 PM
Data Sourced
via MITRE·04:14 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·05:17 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·10:45 PM
Data Sourced
via GitHub·10:45 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are exposed to unintended writes outside the configured destination root?

Deployments using rclone before 1.75.1 are exposed when copying or uploading from a flat-keyspace source store that contains an object name with a raw ".." path segment, and the destination is b2, swift, qingstor, oracleobjectstorage, internetarchive, smb, storj, sftp, webdav, ftp, filelu, shade, or sia.

2

What must an attacker control or influence to exploit this issue?

An attacker needs to cause rclone to process a source object whose Object.Remote() value includes a parent-directory segment. Such object names can exist in flat-keyspace source stores when populated using native non-rclone tooling.

3

How far can an escaped upload reach?

The write can reach another bucket, share, or path that is accessible to the credentials used by the rclone operation. For SFTP and SMB destinations, it may reach other filesystem or share locations under the same login authority.

4

What is the remediation?

Upgrade rclone to version 1.75.1, which fixes the handling of parent-directory segments in source object names before they are passed to destination backends.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203