NPM Package Version Command Injection Vulnerability
Summary
I found a local command injection issue in the package installation flow of MissionSquad/mcp-api.
POST /packages/install accepts a caller-controlled version field. That value is concatenated directly into an npm install shell command and executed with child_process.exec(), which allows shell metacharacters in version to inject additional commands.
Affected Version
@missionsquad/mcp-api 1.11.6
Relevant Code
-
src/controllers/packages.ts:245
this.packageService.installPackage(body)
-
src/services/packages.ts:460
- ``const installCmd = `npm install ${name}${version ? '@' + version : ''}```
-
src/services/packages.ts:462
await exec(installCmd, { cwd: packageDir })
There is package-name validation, but the version field is not validated before being passed into the shell command.
Impact
An attacker able to access the package installation endpoint can execute arbitrary OS commands with the privileges of the running mcp-api process.
Recommended Fix
- Replace
exec() with execFile() or spawn() and pass npm, install, package name, and version as separate arguments.
- Validate
version against a strict npm semver/range allowlist.
- Review the upgrade path as well, since
src/services/packages.ts also constructs upgradeCmd using the untrusted version value.
I have a minimal local reproduction and will add it in a follow-up comment with output and screenshot.
NPM Package Version Command Injection Vulnerability
Summary
I found a local command injection issue in the package installation flow of
MissionSquad/mcp-api.POST /packages/installaccepts a caller-controlledversionfield. That value is concatenated directly into annpm installshell command and executed withchild_process.exec(), which allows shell metacharacters inversionto inject additional commands.Affected Version
@missionsquad/mcp-api1.11.6Relevant Code
src/controllers/packages.ts:245this.packageService.installPackage(body)src/services/packages.ts:460src/services/packages.ts:462await exec(installCmd, { cwd: packageDir })There is package-name validation, but the
versionfield is not validated before being passed into the shell command.Impact
An attacker able to access the package installation endpoint can execute arbitrary OS commands with the privileges of the running
mcp-apiprocess.Recommended Fix
exec()withexecFile()orspawn()and passnpm,install, package name, and version as separate arguments.versionagainst a strict npm semver/range allowlist.src/services/packages.tsalso constructsupgradeCmdusing the untrustedversionvalue.I have a minimal local reproduction and will add it in a follow-up comment with output and screenshot.