GHSA-945v-v9p3-v5xw: Github.com/rclone/rclone Rclone Local `--metadata` Applies Attacker-controlled Vulnerability

LOW
CVSS 3.6
CWE-732
Published
Advisory Summary

GHSA-945v-v9p3-v5xw is a LOW (CVSS 3.6) rclone local `--metadata` applies attacker-controlled vulnerability (CWE-732: Incorrect Permission Assignment for Critical Resource) affecting Github.com/rclone/rclone libraries in the Go ecosystem. The issue involves rclone local `--metadata` applies attacker-controlled mode/uid - setuid binary planted from an untrusted remote. Remediation is available by upgrading affected packages to version 1.74.4.

GHSA-945v-v9p3-v5xw at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-945v-v9p3-v5xw
Severity LOW
CVSS v3.1 Base Score 3.6
CWE Classification CWE-732: Incorrect Permission Assignment for Critical Resource
Affected Product Github.com/rclone/rclone
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 3.6

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N).

Attack Vector Local (AV:L)
Attack Complexity High (AC:H)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity Low (I:L)
Availability None (A:N)

How to Fix GHSA-945v-v9p3-v5xw

To remediate this vulnerability, upgrade all affected Github.com/rclone/rclone dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/rclone/rclone fixed: 1.74.4
Upgrade github.com/rclone/rclone to 1.74.4
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/rclone/rclone

How to Check if You Are Affected

To determine whether your application is affected by GHSA-945v-v9p3-v5xw, inspect your project dependencies for Github.com/rclone/rclone:

inspect dependencies for github.com/rclone/rclone

Analyze the terminal output to locate any version of Github.com/rclone/rclone in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.74.4), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-732: Incorrect Permission Assignment for Critical Resource, where the product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors. In Github.com/rclone/rclone, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary When writing an object with metadata, the local backend applies the source-supplied `mode`, `uid`, and `gid` verbatim: it parses `mode` as an octal integer and passes it straight into `os.Chmod(o.path, os.FileMode(umode))`, and passes `uid`/`gid` straight into `os.Chown`. The value is never masked to permission bits, so any value with Go's `ModeSetuid` (1<<23) or `ModeSetgid` (1<<22) bit set causes the setuid/setgid bit to be applied. Because both the file content and its metadata come from the (attacker-controlled) source remote, an attacker stores a binary of their choosing with `mode = 40000755` (and `uid = 0`); when the victim runs `rclone copy -M <remote>: /dest`, rclone writes the attacker's binary and makes it setuid. If the victim runs rclone as root (typical for system backup/restore), the `uid=0` chown plus setuid produces a root-owned setuid binary with attacker content — any local user then escalates to root. When rclone runs as a non-root service user, the planted setuid binary is owned by that user, giving any local user that user's privileges (lateral escalation / persistent backdoor). ### Details `backend/local/metadata.go`, `writeMetadataToFile()`: ```go uid, hasUID := o.parseMetadataInt(m, "uid", 10) gid, hasGID := o.parseMetadataInt(m, "gid", 10) if hasUID { ... err = os.Chown(o.path, uid, gid) // source-controlled owner, no same-uid guard } mode, hasMode := o.parseMetadataInt(m, "mode", 8) if hasMode && mode >= 0 { umode := uint(mode) if umode <= math.MaxUint32 { err = os.Chmod(o.path, os.FileMode(umode)) // <-- raw value; ModeSetuid/ModeSetgid NOT masked off } } ``` `os.Chmod`/`os.FileMode` honor `ModeSetuid`/`ModeSetgid`/`ModeSticky`. There is no `&^ (os.ModeSetuid|os.ModeSetgid)` mask and no check that the source is trusted, so an attacker-chosen `mode` string sets those bits on the freshly written, attacker-controlled file. (Note: a legitimate local source reports `mode` in unix `st_mode` layout e.g. `0106755`, whose bit 1<<23 is unset, so honest copies happen to drop setuid — but the attacker supplies the Go-`FileMode` layout `40000755` directly, which sets it.) ### PoC 1) Get the official stable binary: ``` curl -fsSLO https://downloads.rclone.org/v1.74.3/rclone-v1.74.3-linux-amd64.zip unzip -j rclone-v1.74.3-linux-amd64.zip '*/rclone' -d . # ./rclone -> v1.74.3 ``` 2) Create a payload (the attacker-controlled binary content) and copy it with the malicious `mode` metadata: ``` mkdir -p msrc mdst && cp /bin/true msrc/payload ./rclone copy -M --metadata-set mode=40000755 msrc mdst # 40000755 = Go FileMode setuid|0755 ``` 3) Observe — the destination file is now setuid: ``` stat -c '%A %a' mdst/payload -rwsr-xr-x 4755 # 's' = setuid bit SET on attacker binary ``` Variants: `mode=20000755` → setgid (`-rwxr-sr-x`); `mode=60000755` → both (`-rwsr-sr-x`). With rclone run as root and the source object also carrying `uid=0`/`gid=0`, the file is chown'd root:root, yielding a root-owned setuid binary executable by any local user. ### Impact A victim performing a metadata-preserving copy/restore (`-M`) from an untrusted or compromised remote installs an attacker-chosen executable with the setuid/setgid bit set. Run as root (system backup/restore, the common case for `--metadata`), this is a root-owned setuid root backdoor executable by any local user → local privilege escalation to root. Run as a non-root user, it is a setuid backdoor for that service account. The companion `uid`/`gid` application lets a root-run transfer also reassign ownership of written files arbitrarily. ### Remediation Mask special bits before applying mode from metadata — `os.Chmod(o.path, os.FileMode(umode).Perm())` (or `umode & 0o777`) — and do not honor setuid/setgid/sticky from source metadata; gate `uid`/`gid`/setuid application behind an explicit opt-in (e.g. `--local-metadata-set-ownership`) that is off by default, and document that `-M` from untrusted remotes must not restore privileged bits. Regression test: copying an object with `mode=40000755`/`uid=0` must produce a non-setuid, caller-owned file unless the opt-in is set.

GHSA-945v-v9p3-v5xw Affected Github.com/rclone/rclone Versions

1 component(s)
Fixed Versions:
1.74.4
Product / Package Ecosystem Affected Versions Fixed Version
github.com/rclone/rclone
Go
< 1.74.4
1.74.4

References

Frequently Asked Questions

What is GHSA-945v-v9p3-v5xw?
GHSA-945v-v9p3-v5xw is a security vulnerability in Github.com/rclone/rclone involving rclone local `--metadata` applies attacker-controlled mode/uid - setuid binary planted from an untrusted remote under CWE-732: Incorrect Permission Assignment for Critical Resource.
Which Github.com/rclone/rclone versions are affected?
Affected versions include releases prior to 1.74.4 across affected packages: github.com/rclone/rclone.
What version fixes GHSA-945v-v9p3-v5xw?
Upgrading to 1.74.4 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/rclone/rclone affected?
Yes, github.com/rclone/rclone is affected in releases prior to 1.74.4. Upgrade your dependency to 1.74.4 or later.
What is the CVSS score of GHSA-945v-v9p3-v5xw?
GHSA-945v-v9p3-v5xw has a CVSS v3.1 base score of 3.6 (LOW) with vector string CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N.
What CWE is associated with GHSA-945v-v9p3-v5xw?
GHSA-945v-v9p3-v5xw is classified under CWE-732: Incorrect Permission Assignment for Critical Resource (The product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors.).
How can I check Go dependencies for GHSA-945v-v9p3-v5xw?
Run the dependency tree command: 'inspect dependencies for github.com/rclone/rclone'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-945v-v9p3-v5xw",
  "modified" : "2026-08-05T20:03:14Z",
  "published" : "2026-08-05T20:03:14Z",
  "aliases" : [ ],
  "summary" : "rclone local `--metadata` applies attacker-controlled mode/uid - setuid binary planted from an untrusted remote",
  "details" : "### Summary\nWhen writing an object with metadata, the local backend applies the source-supplied `mode`, `uid`, and `gid` verbatim: it parses `mode` as an octal integer and passes it straight into `os.Chmod(o.path, os.FileMode(umode))`, and passes `uid`/`gid` straight into `os.Chown`. The value is never masked to permission bits, so any value with Go's `ModeSetuid` (1<<23) or `ModeSetgid` (1<<22) bit set causes the setuid/setgid bit to be applied. Because both the file content and its metadata come from the (attacker-controlled) source remote, an attacker stores a binary of their choosing with `mode = 40000755` (and `uid = 0`); when the victim runs `rclone copy -M <remote>: /dest`, rclone writes the attacker's binary and makes it setuid. If the victim runs rclone as root (typical for system backup/restore), the `uid=0` chown plus setuid produces a root-owned setuid binary with attacker content — any local user then escalates to root. When rclone runs as a non-root service user, the planted setuid binary is owned by that user, giving any local user that user's privileges (lateral escalation / persistent backdoor).\n\n### Details\n`backend/local/metadata.go`, `writeMetadataToFile()`:\n```go\nuid, hasUID := o.parseMetadataInt(m, \"uid\", 10)\ngid, hasGID := o.parseMetadataInt(m, \"gid\", 10)\nif hasUID {\n    ...\n    err = os.Chown(o.path, uid, gid)        // source-controlled owner, no same-uid guard\n}\nmode, hasMode := o.parseMetadataInt(m, \"mode\", 8)\nif hasMode && mode >= 0 {\n    umode := uint(mode)\n    if umode <= math.MaxUint32 {\n        err = os.Chmod(o.path, os.FileMode(umode))   // <-- raw value; ModeSetuid/ModeSetgid NOT masked off\n    }\n}\n```\n`os.Chmod`/`os.FileMode` honor `ModeSetuid`/`ModeSetgid`/`ModeSticky`. There is no `&^ (os.ModeSetuid|os.ModeSetgid)` mask and no check that the source is trusted, so an attacker-chosen `mode` string sets those bits on the freshly written, attacker-controlled file. (Note: a legitimate local source reports `mode` in unix `st_mode` layout e.g. `0106755`, whose bit 1<<23 is unset, so honest copies happen to drop setuid — but the attacker supplies the Go-`FileMode` layout `40000755` directly, which sets it.)\n\n### PoC\n1) Get the official stable binary:\n```\ncurl -fsSLO https://downloads.rclone.org/v1.74.3/rclone-v1.74.3-linux-amd64.zip\nunzip -j rclone-v1.74.3-linux-amd64.zip '*/rclone' -d .      # ./rclone -> v1.74.3\n```\n2) Create a payload (the attacker-controlled binary content) and copy it with the malicious `mode` metadata:\n```\nmkdir -p msrc mdst && cp /bin/true msrc/payload\n./rclone copy -M --metadata-set mode=40000755 msrc mdst       # 40000755 = Go FileMode setuid|0755\n```\n3) Observe — the destination file is now setuid:\n```\nstat -c '%A %a' mdst/payload\n-rwsr-xr-x 4755                                               # 's' = setuid bit SET on attacker binary\n```\nVariants: `mode=20000755` → setgid (`-rwxr-sr-x`); `mode=60000755` → both (`-rwsr-sr-x`). With rclone run as root and the source object also carrying `uid=0`/`gid=0`, the file is chown'd root:root, yielding a root-owned setuid binary executable by any local user.\n\n\n### Impact\nA victim performing a metadata-preserving copy/restore (`-M`) from an untrusted or compromised remote installs an attacker-chosen executable with the setuid/setgid bit set. Run as root (system backup/restore, the common case for `--metadata`), this is a root-owned setuid root backdoor executable by any local user → local privilege escalation to root. Run as a non-root user, it is a setuid backdoor for that service account. The companion `uid`/`gid` application lets a root-run transfer also reassign ownership of written files arbitrarily.\n\n### Remediation\nMask special bits before applying mode from metadata — `os.Chmod(o.path, os.FileMode(umode).Perm())` (or `umode & 0o777`) — and do not honor setuid/setgid/sticky from source metadata; gate `uid`/`gid`/setuid application behind an explicit opt-in (e.g. `--local-metadata-set-ownership`) that is off by default, and document that `-M` from untrusted remotes must not restore privileged bits. Regression test: copying an object with `mode=40000755`/`uid=0` must produce a non-setuid, caller-owned file unless the opt-in is set.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/rclone/rclone"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.74.4"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 1.74.3"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/rclone/rclone/security/advisories/GHSA-945v-v9p3-v5xw"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/rclone/rclone/commit/e58f09739a35774ca82b5211d2377ac0f2051500"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/rclone/rclone"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/rclone/rclone/releases/tag/v1.74.4"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-732" ],
    "severity" : "LOW",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-05T20:03:14Z",
    "nvd_published_at" : null
  }
}