Security Advisory: `makeBinaryWrapper`: empty PATH segments enable current-directory hijacking

Summary

makeBinaryWrapper/makeCWrapper implements --prefix/ --suffix by concatenating the given value onto a search-path environment variable (PATH, LD_LIBRARY_PATH…) without checking whether that value is empty.

When the value is empty (e.g. because the provided value was the result of lib.makeBinPath over an empty list) an empty path segment will be added into the variable. POSIX shells and execvp() will consider the empty path segment as the current working directory.

Impact

An attacker who can place a file with a specific name in a directory the victim later runs an affected tool from (an untrusted git checkout, a downloaded archive…) can get that file silently executed or loaded as a library.
This can result on full code execution or a Denial of Service for some commands when the programming language includes some additional protection (see Go ErrDot for example).

Am I affected?

You are impacted if you are using a package using makeBinaryWrapper with --prefix/--suffix on a path value variable that can be empty during the build.

The nixpkgs security team identified the following impacted packages:

  • zellij
  • treefmt.withConfig (limited DoS due to Go restrictions)
  • docker CLI (limited DoS due to Go restrictions)
  • buildah (only for Darwin and limited DoS due to Go restrictions)
  • lispWithPackages
  • qt6Packages.fcitx5-with-addons
  • ocelot-desktop (only for x86_64-darwin)

zellij is the most critical one in the packages we identified due to its nature and the absence of other mitigations.

Note the list might not be exhaustive due to the large nixpkgs package set and potential usages outside of nixpkgs.

You can use the following script to identify binaries in your /nix/store that might be impacted by the issue:

#! /usr/bin/env nix-shell
#! nix-shell -i bash --pure
#! nix-shell -p findutils gnugrep gawk binutils

set -uo pipefail

STORE="${1:-/nix/store}"

printf 'BINARY\tFLAG\tENV_VAR\tVALUE\n'

while read -r f; do
    grep -qF 'makeCWrapper' "$f" || continue

    strings -a -- "$f" | awk -F"'" -v bin="$f" '
        /--prefix |--suffix / {
            flag = ($0 ~ /--prefix /) ? "--prefix" : "--suffix"
            env  = $2
            sep  = $4
            val  = $6
            if (sep == "") next
            wrapped_val = sep val sep
            doubled = sep sep
            if (index(wrapped_val, doubled) > 0) {
                printf "%s\t%s\t%s\t[%s]\n", bin, flag, env, val
                found = 1
            }
        }
        END { exit (found ? 0 : 1) }
    '
done < <(find "$STORE" -type f -executable)

What do I need to do?

Update, you can track the progress of the different pull-requests below.
In the meantime, until patched avoid running any affected tool from a directory with content you do not trust.

Fixes:

Acknowledgement

Thank you to cielavenir for reporting the issue with the docker CLI to the nixpkgs security team.

Reference

15 Likes

Surprised it’s this few packages with this mega-footgun (similar to empty entries in LD_LIBRARY_PATH).

Looks like reviewers were doing a good job!