CVE-2022-24066 (TypeScript, published 2022-04-01T20:15Z)
Description: value: The package simple-git before 3.5.0 are vulnerable to Command Injection due to an incomplete fix of [CVE-2022-24433](https://security.snyk.io/vuln/SNYK-JS-SIMPLEGIT-2421199) which only patches against the git fetch attack vector. A similar use of the --upload-pack feature of git is also supported for git clone, which the prior fix didn't cover.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-88 \u2014 Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')
The product constructs a string for a command to be executed by a separate component
in another control sphere, but it does not properly delimit the
intended arguments, options, or switches within that command string.
Repository: https://github.com/steveukx/git-js
Files changed:
.changeset/wicked-files-vanish.md
simple-git/src/lib/tasks/clone.ts
simple-git/test/unit/clone.spec.ts
Commit message: Prevent use of `--upload-pack` as a command in `git.clone` to avoid potential accidental command execution.


Vulnerable code:
import { straightThroughStringTask } from './task';
import { append } from '../utils';
   OptionFlags<
      '--bare' |
      '--verbose'
      > &
export function cloneTask(repo: string | undefined, directory: string | undefined, customArgs: string[]): StringTask<string> {
   if (typeof repo === 'string') {
      commands.push(repo);
   }
   if (typeof directory === 'string') {
      commands.push(directory);
export function cloneMirrorTask(repo: string | undefined, directory: string | undefined, customArgs: string[]): StringTask<string> {
   append(customArgs,'--mirror');
import { assertExecutedCommands, closeWithSuccess, newSimpleGit } from './__fixtures__';
   it.each(cloneTests)('callbacks - %s %s', async (api, name, cloneArgs, executedCommands)=> {

Fixed code:
---
"simple-git": minor
---

Resolves potential command injection vulnerability by preventing use of `--upload-pack` in `git.clone`
import { configurationErrorTask, EmptyTask, straightThroughStringTask } from './task';
import { append, filterString } from '../utils';
   OptionFlags<'--bare' |
      '--verbose'> &
function disallowedCommand(command: string) {
   return /^--upload-pack(=|$)/.test(command);
}

export function cloneTask(repo: string | undefined, directory: string | undefined, customArgs: string[]): StringTask<string> | EmptyTask {

   filterString(repo) && commands.push(repo);
   filterString(directory) && commands.push(directory);

   const banned = commands.find(disallowedCommand);
   if (banned) {
      return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
export function cloneMirrorTask(repo: string | undefined, directory: string | undefined, customArgs: string[]) {
   append(customArgs, '--mirror');
import { promiseError } from '@kwsites/promise-result';
import { assertExecutedCommands, assertGitError, closeWithSuccess, newSimpleGit } from './__fixtures__';
   it.each(cloneTests)('callbacks - %s %s', async (api, name, cloneArgs, executedCommands) => {

   describe('failures', () => {

      it('disallows upload-pack as remote/branch', async () => {
         const error = await promiseError(git.clone('origin', '--upload-pack=touch ./foo'));

         assertGitError(error, 'potential exploit argument blocked');
      });

      it('disallows upload-pack as varargs', async () => {
         const error = await promiseError(git.clone('origin', 'main', {
            '--upload-pack': 'touch ./foo'
         }));

         assertGitError(error, 'potential exploit argument blocked');
      });

      it('disallows upload-pack as varargs', async () => {
         const error = await promiseError(git.clone('origin', 'main', [
            '--upload-pack', 'touch ./foo'
         ]));

         assertGitError(error, 'potential exploit argument blocked');
      });
   });