Skip to content

fix shell command built from environment values OS Command Injection on utils() #1354

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

odaysec
Copy link

@odaysec odaysec commented Apr 23, 2025

execSync(`git log -1 --pretty="format:%ct" ${filePath}`)

fix the issue should avoid dynamically constructing the shell command with filePath. Instead, we can use execFileSync from the child_process module, which allows us to pass arguments to the command as an array. This approach ensures that the filePath is treated as a literal argument and not interpreted by the shell.

Specifically:

  1. Replace the use of execSync with execFileSync.
  2. Pass the git command and its arguments as separate elements in an array, ensuring filePath is treated safely.

The changes will be made in the fileLastUpdate function on line 64.

Dynamically constructing a shell command with values from the local environment, such as file paths, may inadvertently change the meaning of the shell command. Such changes can occur when an environment value contains characters that the shell interprets in a special way, for instance quotes and spaces. This can result in the shell command misbehaving, or even allowing a malicious user to execute arbitrary commands on the system.

POC

The following shows a dynamically constructed shell command that recursively removes a temporary directory that is located next to the currently executing JavaScript file. Such utilities are often found in custom build scripts.

var cp = require("child_process"),
  path = require("path");
function cleanupTemp() {
  let cmd = "rm -rf " + path.join(__dirname, "temp");
  cp.execSync(cmd); // BAD
}

The shell command will, however, fail to work as intended if the absolute path of the script's directory contains spaces. In that case, the shell command will interpret the absolute path as multiple paths, instead of a single path.

For instance, if the absolute path of the temporary directory is /home/username/important opensea/temp, then the shell command will recursively delete /home/username/important and opensea/temp, where the latter path gets resolved relative to the working directory of the JavaScript process.

Even worse, although less likely, a malicious user could provide the path /home/username/; cat /etc/passwd #/important opensea/temp in order to execute the command cat /etc/passwd.

To avoid such potentially catastrophic behaviors, provide the directory as an argument that does not get interpreted by a shell:

var cp = require("child_process"),
  path = require("path");
function cleanupTemp() {
  let cmd = "rm",
    args = ["-rf", path.join(__dirname, "temp")];
  cp.execFileSync(cmd, args); // GOOD
}

References

Command Injection
CWE-78
CWE-88

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant