~ 3 min read
Disclosing a Command Injection Vulnerability in `git-checkout-tool`

Nowadays when everyone work around source control, it is quite trivial use-case for backend systems to clone a git repository, checkout a branch and do something with it - build, test, deploy, run stats, etc. What happens when your git clone workflow uses a third-party library that has a command injection vulnerability? This is the story of git-checkout-tool
and a command injection vulnerability.
So, git-checkout-tool
is a command-line tool that allows users to checkout git repositories based on a branch name that it prompts for interactively. It is available as an npm package and can be installed via npm install -g git-checkout-tool
.
Resources:
- Project’s GitHub code repository: https://github.com/jamespeach02/git-checkout-tool
- Project’s npm package: https://www.npmjs.com/package/git-checkout-tool
Command Injection Vulnerability
The git-checkout-tool
tool is vulnerable to a command injection vulnerability due to the way it constructs the git checkout
command that it runs.
It uses user input to capture the branch name, which it then feeds straight into Node.js child process module exec()
function, which interpolates the input via a shell program, making it susceptible to command injection attacks.
The vulnerable code:
const makeCheckout = command => { exec(command, function(err,stdout, stderr) { if (err) { console.log (err); return; } if (stdout.length > 0) console.log(`${stdout.toString("utf8")}`); if (stderr.length > 0) console.log(`${stderr.toString("utf8")}`); });};
console.log("Select a branch to checkout");inquirer.prompt(questions).then(answers => { let branch = JSON.stringify(answers.branch, null, " "); let branchCleaned = branch.slice(1, branch.length - 1); makeCheckout( `git checkout ${branchCleaned}` );});
đź‘‹ Just a quick break
I'm Liran Tal and I'm the author of the newest series of expert Node.js Secure Coding books. Check it out and level up your JavaScript
Exploit Proof of Concept
- Install the
git-checkout-tool
package:
npm install git-checkout-tool
- Run the
git-checkout-tool
command and in the interactive prompt, enter the following branch name to exploit the command injection:
$ npx git-checkout-tool
- Enter the following branch name:
hello ; echo 'Command Injection Vulnerability Exploited!' > /tmp/command-injection.txt; #
Vulnerable versions
All versions of git-checkout-tool are vulnerable to this issue, up to and including to the latest version of 1.0.6
.
Impact
Let’s examine this vulnerability’s impact from a real-world and practical perspective:
- The
git-checkout-tool
is a tool intended to run by developers and users on their own local machines. - The tool is designed to run via interactivity on the command-line.
- How different is this tool from the user running
git checkout something; touch /tmp/self-harm.txt
? Not much.
However, here is where I want to draw the line - adversarial entities will take all measures possible to exploit any vulnerability, no matter how small it is, in order to gain leverage.
So can I think of a real-world case? of course I can. Here is one.
Git is known to be a very powerful tool, and often developers don’t understand it to the full extent and use a very minimal set of commands and capabilities. Next, what if a developer using a tool like git-checkout-tool
as part of a tutorial they follow? and what if they copy-and-paste a malicious command from a blog post, or a reddit comment? and that command they copied used techniques to hide the malicious branch name from the user by employing base64 encoding, trojan source text (e.g hidden characters using polyglyphs), or other means?
At the end of the day, what I want to stress is that security is multi-layered, and we should urge and demand secure-by-design and secure-by-default software.
I’ll leave you with that positive note :-)