go-git is a popular and highly extensible library for handling Git repositories in Go programs. Using only pure Go code, it shields many developers from the hassle of calling external binaries. But, if you’re relying on old versions of go-git (any version before 5.13.), you might be exposed to a serious vulnerability: CVE-2025-21613. In this article, we’ll break down what happened, why it’s dangerous, and how an attacker could exploit it, using simple language and easy-to-read code snippets.

What is CVE-2025-21613?

CVE-2025-21613 is an argument injection vulnerability found in go-git versions before v5.13.. The bug allows an attacker to pass arbitrary flags to git-upload-pack when using the file transport protocol. This could let attackers trick the Go application into running git commands with unexpected (potentially dangerous) parameters.

Note: This is only exploitable through the file protocol (file://), which is the only mode where go-git starts an actual git binary process under the hood.

References:
- GitHub Advisory
- Go-git Release Notes
- NIST NVD Record (expected)

Why Is This a Big Deal?

With argument injection, attackers can manipulate command-line flags. In the context of git-upload-pack, this could:

Or, in some environments, even allow code execution—depending on how the binary interprets flags.

Who’s at risk?
Any Go application using go-git before v5.13., that allows user-controlled repository URLs using the file:// protocol.

How Does the Vulnerability Work?

When go-git handles a file:// remote, it calls the system’s Git binary for certain operations. Before version 5.13., it naïvely passed user-supplied paths almost verbatim:

Unsafe code illustration (simplified)

cmd := exec.Command("git-upload-pack", userInputRepoPath)
cmd.Run()

If userInputRepoPath contains something like

/some/repo --advertise-refs --foo=bar

then those extra flags (--advertise-refs, --foo=bar) are passed directly to git-upload-pack.

Example of a crafted repository URL that injects flags

file:///tmp/myrepo --advertise-refs --strict

When go-git calls the system Git, your flags sneak right in.

Imagine a web service that lets users sync with a local repo using a form like

func syncRepo(userRepoPath string) error {
    repo, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
        URL: "file://" + userRepoPath,
    })
    return err
}

An attacker submits this as userRepoPath

/tmp/testrepo --upload-pack=/malicious/binary

The resulting shell command

git-upload-pack /tmp/testrepo --upload-pack=/malicious/binary

Depending on environment and permissions, /malicious/binary could be executed or, at the very least, unexpected behavior is triggered.

Proof-of-Concept (PoC) snippet

// File: go-git-inject-demo.go
package main

import (
    "github.com/go-git/go-git/v5" // Make sure this is < v5.13. for demo
)

func main() {
    // Injected arguments after space
    repoURL := "file:///tmp/testrepo --advertise-refs"
    _, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
        URL: repoURL,
    })
    if err != nil {
        panic(err) // Should fail or behave unpredictably
    }
}

Warning: Don’t run with untrusted paths – this is only to demo the vulnerability!

How Is It Fixed?

From v5.13. onward, go-git sanitizes and safely passes arguments. It now ensures user input is interpreted strictly as a path, not as flags.

See the v5.13. changelog for full details.

`bash

go get github.com/go-git/go-git/v5@v5.13.

Validate all user input

Never use untrusted strings to build repository paths—sanitize or explicitly allow only known directories.

Avoid the file protocol

Unless it’s absolutely necessary, use other remote protocols (HTTPS, SSH) that don’t have this risk.

More Reading

- go-git Documentation
- Common Go security pitfalls
- About argument injection vulnerabilities (OWASP)

Conclusion

CVE-2025-21613 shows that even pure Go libraries can be vulnerable if they shell out to system binaries with user-controlled arguments. If you use go-git, double-check your version, audit your use of the file:// protocol, and upgrade if needed. Spread the word to keep the Go ecosystem safe!

Timeline

Published on: 01/06/2025 17:15:47 UTC