rust-lang / rust-lang/rustup

Invoking cargo completions in malicious project may lead to RCE

Open
#3,740 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug help wanted
Dominant language
Rust
Stars
7k
Forks
1.1k
Avg merge
22h 40m
Merged PRs (30d)
46

Description

A simple repro would be a project dir with the following contents:

rust-toolchain.toml:

[toolchain]
path = "/path/to/project"

bin/cargo (executable bit set):

#!/usr/bin/env bash
echo "Malicious code executed" > oops.txt

And that's it. If you now try to do shell completion in bash for "cargo check --bin " (trailing space important to avoid getting "--bin" and "--bins" as completions), a file called oops.txt will be created with "Malicious code executed" as content. (This needs the cargo bash completion to be enabled)

This RCE works because the cargo completion invokes cargo to get the list of bin targets. When using rustup, rustup will try to invoke the cargo of the active toolchain, which in this case is the project directory itself thanks to the rust-toolchain.toml file and as such bin/cargo in the project directory is invoked.

While it would be true that actually running the cargo command would allow running arbitrary code already, this is a lot more widely known and less surprising. I don't expect completions to have any side-effects like running malicious code in the POC.

This issue is mostly disclosed already in https://github.com/rust-lang/cargo/issues/6645#issuecomment-1889975423 as I didn't realize that the current state of the cargo completions already allow this. No POC has been posted there though.

For reference oh-my-zsh used to have a similar RCE opportunity by running "rustup run completions zsh cargo" whenever opening a new shell. This would run "cargo completions zsh" for the active toolchain of the directory in which the shell was opened. After I reported this, it was changed to use the default toolchain instead in https://github.com/ohmyzsh/ohmyzsh/commit/a01cf8562700f3e5594f66daf40f31d9fe7ec570

The POC is shared with the security team made use of path = "." which no longer works as of https://github.com/rust-lang/rustup/pull/3340. According to https://github.com/rust-lang/rustup/issues/3461 it should be possible to use /proc/self/cwd as workaround, but I couldn't get this to work on my machine. For a targeted attack it is likely still possible to guess the location where the victim will clone the malicious project.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the report from a project containing rust-toolchain.toml with a path toolchain and an executable bin/cargo, with cargo Bash completion enabled. Trace how completion invokes cargo through rustup and verify the behavior across the referenced toolchain-path cases. Done means completion no longer executes project-controlled code or causes side effects.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, rust
Domain
cli, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.