flawopen.com/Teardowns/CVE-2024-32002

CVE-2024-32002: Git Submodule Symlink RCE

Critical 9.8 CWE-78 / CWE-59 Git < 2.45.1
Languages: en pt-br es fr de ru zh-cn ja hi ko id
ELI5 — The Deceptive Office Sign

Imagine a courier delivering an internal company package to 'Room 101'. An attacker places a sign on door 101 saying 'Room 101 has moved to the Executive Safe'. Instead of checking if that sign is legitimate, the courier blindly follows the arrow into the safe and drops off a bomb. In Git, the courier was the submodule cloner, the deceptive sign was a symlink, and the safe was the hidden .git/hooks/ directory where executable scripts automatically trigger.

Target: Git core CLI
Vector: git clone --recursive <url>
Impact: Remote Code Execution (RCE)
Platform: macOS & Windows (Case-Insensitive Filesystems)

The Fatal Git Source Code Diff

In builtin/submodule--helper.c and dir.c, Git initialized the submodule worktree without verifying whether any parent directory element along the clone path was an existing symlink pointing outside the working tree.

builtin/submodule--helper.c (Vulnerable)Vulnerable
// Git clone created submodule directory blindly
static int clone_submodule(const struct module_clone_data *clone_data)
{
    struct strbuf sb = STRBUF_INIT;

    // BUG: clone_data->path could traverse an existing symlink
    strbuf_addf(&sb, "%s", clone_data->path);
    safe_create_leading_directories(sb.buf);
    return do_clone(clone_data);
}
builtin/submodule--helper.c (Fixed)Patched
// Fixed: Refuse to clone into or through symlinked path components
static int clone_submodule(const struct module_clone_data *clone_data)
{
    struct strbuf sb = STRBUF_INIT;

    // FIX: Validate that no parent component is a symlink
    if (path_has_symlinks(clone_data->path))
        die(_("fatal: submodule path '%s' contains a symlink"),
            clone_data->path);

    strbuf_addf(&sb, "%s", clone_data->path);
    return do_clone(clone_data);
}

The 3-Step Exploit Flow

Key Engineering Takeaways for Developers

Explore more vulnerability mechanisms & language matrices: Command Injection Matrix →