VYPR
Moderate severityNVD Advisory· Published Feb 26, 2022· Updated Aug 2, 2024

Arbitrary Command Injection in strapi/strapi

CVE-2022-0764

Description

Arbitrary Command Injection in GitHub repository strapi/strapi prior to 4.1.0.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A command injection vulnerability in Strapi before 4.1.0 allows arbitrary command execution via unsanitized package name input to the CLI.

Vulnerability

An arbitrary command injection vulnerability exists in Strapi versions prior to 4.1.0. The flaw resides in the CLI helper functions getPackageInfo, getStarterPackageInfo, and downloadNpmStarter located in the file packages/strapi-generate-new/lib/utils/helpers.js. These functions used execa.command() with user-controlled package names, constructing shell commands without proper sanitization. The affected code path is reachable when a user runs Strapi's CLI commands that involve fetching or installing npm packages, such as npx create-strapi my-project --template @strapi/.... The issue was fixed in commit 2a3f5e988be6a2c7dae5ac22b9e86d579b462f4c which replaced execa.command() with execa() passing arguments as an array, preventing shell injection [1][2][3][4].

Exploitation

An attacker would need to convince a victim to run the Strapi CLI with a malicious package name as an argument. For example, constructing a template or plugin name that includes shell metacharacters. No authentication is required as the CLI runs directly in the user's shell. The attacker does not need any network position beyond the ability to communicate the malicious string (e.g., via social engineering or by hosting a malicious package). The concrete sequence is: the victim executes a Strapi CLI command (e.g., npx create-strapi my-project --template @attacker/malicious-name`), the CLI passes the attacker-controlled string to the vulnerable functions, the shell interprets the injected commands, and they run with the privileges of the victim user [3].

Impact

Successful exploitation allows an attacker to execute arbitrary commands on the victim's system with the same privileges as the user running the CLI. This can lead to full compromise of the development machine, including data theft, installation of malware, or lateral movement within the network. The impact is limited to users who run the CLI with a malicious package name, but it does not require authenticated access to a Strapi instance [2][3].

Mitigation

The vulnerability is fixed in Strapi version 4.1.0, released on 2022-02-28. Users should upgrade to 4.1.0 or later. There is no known workaround; users must avoid running the Strapi CLI with untrusted package names. The fix is available in the referenced commit and was incorporated into the 4.1.0 release [2][3].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
strapinpm
< 4.1.04.1.0

Affected products

2
  • ghsa-coords
    Range: < 4.1.0
  • strapi/strapi/strapiv5
    Range: unspecified

Patches

1
2a3f5e988be6

Merge pull request #12649 from strapi/cli-security

https://github.com/strapi/strapiAlexandre BODINFeb 24, 2022via ghsa
2 files changed · +6 6
  • packages/cli/create-strapi-starter/utils/fetch-npm-starter.js+4 4 modified
    @@ -15,7 +15,7 @@ const stopProcess = require('./stop-process');
     async function getPackageInfo(packageName, { useYarn } = {}) {
       // Use yarn if possible because it's faster
       if (useYarn) {
    -    const { stdout } = await execa.command(`yarn info ${packageName} --json`);
    +    const { stdout } = await execa('yarn', ['info', packageName, '--json']);
         const yarnInfo = JSON.parse(stdout);
         return {
           name: yarnInfo.data.name,
    @@ -24,7 +24,7 @@ async function getPackageInfo(packageName, { useYarn } = {}) {
       }
     
       // Fallback to npm
    -  const { stdout } = await execa.command(`npm view ${packageName} name version --silent`);
    +  const { stdout } = await execa('npm', ['view', packageName, 'name', 'version', '--silent']);
       // Use regex to parse name and version from CLI result
       const [name, version] = stdout.match(/(?<=')(.*?)(?=')/gm);
       return { name, version };
    @@ -67,11 +67,11 @@ async function getStarterPackageInfo(starter, { useYarn } = {}) {
     async function downloadNpmStarter({ name, version }, parentDir, { useYarn } = {}) {
       // Download from npm, using yarn if possible
       if (useYarn) {
    -    await execa.command(`yarn add ${name}@${version} --no-lockfile --silent`, {
    +    await execa('yarn', ['add', `${name}@${version}`, '--no-lockfile', '--silent'], {
           cwd: parentDir,
         });
       } else {
    -    await execa.command(`npm install ${name}@${version} --no-save --silent`, {
    +    await execa('npm', ['install', `${name}@${version}`, '--no-save', '--silent'], {
           cwd: parentDir,
         });
       }
    
  • packages/generators/app/lib/utils/fetch-npm-template.js+2 2 modified
    @@ -10,7 +10,7 @@ const chalk = require('chalk');
      * @returns {Object}
      */
     async function getPackageInfo(packageName) {
    -  const { stdout } = await execa.shell(`npm view ${packageName} name version --silent`);
    +  const { stdout } = await execa('npm', ['view', packageName, 'name', 'version', '--silent']);
       // Use regex to parse name and version from CLI result
       const [name, version] = stdout.match(/(?<=')(.*?)(?=')/gm);
       return { name, version };
    @@ -46,7 +46,7 @@ async function getTemplatePackageInfo(template) {
      */
     async function downloadNpmTemplate({ name, version }, parentDir) {
       // Download from npm
    -  await execa.shell(`npm install ${name}@${version} --no-save --silent`, {
    +  await execa('npm', ['install', `${name}@${version}`, '--no-save', '--silent'], {
         cwd: parentDir,
       });
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.