git-clone-safe
v1.2.0
Published
Safe drop-in replacement for git-clone package, fixing command injection vulnerability (CVE-2022-25900)
Maintainers
Readme
git-clone-safe
Safe drop-in replacement for git-clone package, fixing command injection vulnerability (CVE-2022-25900)
Purpose
This is a fully functional replacement for the vulnerable [email protected] package. It provides the same API but fixes the command injection vulnerability (CVE-2022-25900) by using child_process.spawn instead of shell-based execution.
Why This Works
- The original
git-clonepackage has a command injection vulnerability (CVE-2022-25900) due to using shell-based command execution - This package uses
child_process.spawnwhich passes arguments directly to the git binary without a shell - Uses
--separator before the repository URL to prevent git option injection - No command injection is possible because user input is never passed through a shell
API Compatibility
This package provides the same API as the original git-clone:
Callback API
const gitClone = require('git-clone-safe');
gitClone(repo, targetPath, opts, cb)Promise API
const gitClone = require('git-clone-safe/promise');
await gitClone(repo, targetPath, opts)Options (matching original git-clone API)
| Option | Type | Description |
|--------|------|-------------|
| git | String | Path to git executable (default: 'git') |
| shallow | Boolean | Clone with depth 1 (shallow clone) |
| checkout | String | Branch, tag, or commit SHA to checkout |
| args | Array|String | Additional git arguments (array of strings, or space-separated string) |
| emit | Boolean | Emit stdio to parent process (default: false) |
Notes:
branchis supported as an alias forcheckoutfor backward compatibilitydepth(numeric) takes precedence overshallowif both are specifiedcheckoutperforms a separategit checkoutafter cloning, which works for branches, tags, AND commit SHAsargsas an array follows the original API; string format is also accepted for convenience
Setup
Add an override in your project's package.json:
"overrides": {
"git-clone": "npm:git-clone-safe"
}Or use a local path:
"overrides": {
"git-clone": "file:./git-clone-safe"
}Usage Example
const gitClone = require('git-clone-safe');
// Clone a specific branch
gitClone(
'https://github.com/user/repo.git',
'./my-repo',
{ checkout: 'main' },
(err) => {
if (err) {
console.error('Clone failed:', err);
} else {
console.log('Clone successful!');
}
}
);
// Shallow clone
gitClone(
'https://github.com/user/repo.git',
'./my-repo',
{ shallow: true },
(err) => { /* ... */ }
);
// With custom git path and extra args (array format - original API)
gitClone(
'https://github.com/user/repo.git',
'./my-repo',
{ git: '/usr/bin/git', args: ['--verbose'] },
(err) => { /* ... */ }
);
// Checkout a specific commit SHA
gitClone(
'https://github.com/user/repo.git',
'./my-repo',
{ checkout: 'a1b2c3d' },
(err) => { /* ... */ }
);Security Fix
Vulnerability #1: Shell Command Injection (CVE-2022-25900)
The original git-clone package used child_process.exec() which passes commands through a shell. This allowed attackers to inject arbitrary commands:
// Malicious input
gitClone('https://evil.com/repo.git && rm -rf /', './dest')
// Would execute via shell: git clone 'https://evil.com/repo.git && rm -rf /' './dest'Fix: Use child_process.spawn() with an array of arguments - no shell involved.
Vulnerability #2: Git Option Injection
Without proper argument separation, a repository name starting with - could be interpreted as a git option:
// Without -- separator
spawn('git', ['clone', '--help', './dest']) // Shows help instead of cloning
// With -- separator
spawn('git', ['clone', '--', '--help', './dest']) // Actually clones repo named "--help"Fix: Always use -- before the repository URL to terminate option parsing.
Vulnerability #3: Unsafe args Parameter
The original package concatenated opts.args directly into the shell command, allowing shell injection.
Fix: Accept opts.args as an array of strings (original API) or a space-separated string. Each element is validated to reject shell metacharacters (;&|$()<>`) before being passed to git.
Verification
Check that the override is active:
npm ls git-clone
# Should show: git-clone@npm:[email protected]
npm audit
# Should NOT report git-clone vulnerabilityImpact
- ✅ Fixes security scanner findings (CVE-2022-25900)
- ✅ Fully functional git clone capability
- ✅ Drop-in replacement - same API as original
- ✅ No additional dependencies
- ✅ Protected against git option injection via
--separator
