CVE-2020-28451 (published 2022-08-02T14:15Z)

This affects the package image-tiler before 2.0.2.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-77
cwe_name: Improper Neutralization of Special Elements used in a Command ('Command Injection')
description: The product constructs all or part of a command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended command when it is sent to a downstream component.
extended_description: 
            Many protocols and products have their own custom command language. While OS or shell command strings are frequently discovered and targeted, developers may not realize that these other command languages might also be vulnerable to attacks.
         
         

Fix information:
repo_url: https://github.com/MrP/image-tiler
commit_details: repo_url: https://github.com/MrP/image-tiler
author: Victor Rodriguez
author_date: 2021-01-05 21:34:11+00:00
msg: fix command injection vuln
repository: repo_url: https://github.com/MrP/image-tiler
repo_name: MrP/image-tiler
description: Create zoom tile pyramids from a large image
repo_language: JavaScript
owner: MrP
file_changes: filename: index.js
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,5 @@
 'use strict';
-var execSync = require('child_process').execSync;
+var execFileSync = require('child_process').execFileSync;
 var sizeOf = require('image-size');
 var mkdirp = require('mkdirp-promise');
 var rimraf = require('rimraf-then');
@@ -14,18 +14,18 @@ function tileLevel(inPath, outPath, zoom, tileSize, pattern, quality) {
         .replace(/\.[^.]+$/, '');
     var patternedFilenameWithoutTheFilename = '';
     if (pattern.indexOf(path.sep) > 0) {
-        patternedFilenameWithoutTheFilename = pattern.replace(new RegExp(path.sep+'[^'+path.sep+']*$'), '')
-        .replace(/\{z\}/, '' + zoom);
+        patternedFilenameWithoutTheFilename = pattern.replace(new RegExp(path.sep + '[^' + path.sep + ']*$'), '')
+            .replace(/\{z\}/, '' + zoom);
     }
     return mkdirp(outPath + path.sep + patternedFilenameWithoutTheFilename)
-    .then(()=>{
-        var command = 'convert ' + inPath +
-            ' -crop ' + tileSize + 'x' + tileSize +
-            ' -set filename:tile "' + patternedFilename + '"' +
-            ' -quality ' + quality + ' +repage +adjoin' +
-            ' "' + outPath + '/%[filename:tile]' + dotExtension + '"' ;
-        execSync(command);
-    });
+        .then(() => {
+            var args = [inPath,
+                '-crop', tileSize + 'x' + tileSize,
+                '-set', 'filename:tile', patternedFilename,
+                '-quality', quality, '+repage', '+adjoin',
+                outPath + '/%[filename:tile]' + dotExtension];
+            execFileSync('convert', args);
+        });
 }
 
 function imageBiggerThanTile(path, tileSize) {
@@ -36,7 +36,7 @@ function imageBiggerThanTile(path, tileSize) {
 function tileRec(inPath, outPath, zoom, tileSize, tempDir, pattern, zoomToDisplay, invertZoom, quality) {
     var inPathMpc = tempDir + '/temp_level_' + zoom + '.mpc';
     var inPathCache = tempDir + '/temp_level_' + zoom + '.cache';
-    execSync('convert ' + inPath + ' ' + inPathMpc);
+    execFileSync('convert', [inPath, inPathMpc]);
     return tileLevel(inPathMpc, outPath, zoomToDisplay, tileSize, pattern, quality)
         .then(function () {
             if (imageBiggerThanTile(inPath, tileSize)) {
@@ -46,7 +46,7 @@ function tileRec(inPath, outPath, zoom, tileSize, tempDir, pattern, zoomToDispla
                     newZoomToDisplay = zoomToDisplay - 1;
                 }
                 var newInPath = tempDir + '/temp_level_' + zoom + '.png';
-                execSync('convert ' + inPathMpc + ' -resize 50% -quality ' + quality + ' ' + newInPath);
+                execFileSync('convert', [inPathMpc, '-resize', '50%', '-quality', quality, newInPath]);
                 fs.unlinkSync(inPathMpc);
                 fs.unlinkSync(inPathCache);
                 return tileRec(newInPath, outPath, newZoom, tileSize, tempDir, pattern, newZoomToDisplay, invertZoom, quality);
@@ -72,6 +72,6 @@ module.exports.tile = function (inPath, outPath, pattern, options) {
         zoomToDisplay = Math.max(halvingsWidth, halvingsheight);
     }
     return mkdirp(tempDir)
-        .then(()=>tileRec(inPath, outPath, zoom, tileSize, tempDir, pattern, zoomToDisplay, options.invertZoom, quality))
-        .then(()=>rimraf(tempDir));
+        .then(() => tileRec(inPath, outPath, zoom, tileSize, tempDir, pattern, zoomToDisplay, options.invertZoom, quality))
+        .then(() => rimraf(tempDir));
 };

programming_language: JavaScript
filename: image-tiler.spec.js
change_type: ModificationType.MODIFY
diff: @@ -1,6 +1,6 @@
 /*global jasmine*/
 var fs = require('fs');
-var execSync = require('child_process').execSync;
+var execFileSync = require('child_process').execFileSync;
 var rimraf = require('rimraf');
 var expectImagesToBeTheSame = require('./expectImagesToBeTheSame.helper.js').expectImagesToBeTheSame;
 
@@ -14,10 +14,10 @@ describe('image-tiler cli', function () {
     });
     describe('When used on an image smaller than the tile size', function () {
         it('should output the same image', function (done) {
-            execSync('node bin/image-tiler spec/small.png ' + tempDir + ' small_test_result_{z}_{x}_{y}.png');
+            execFileSync('node', ['bin/image-tiler', 'spec/small.png', tempDir, 'small_test_result_{z}_{x}_{y}.png']);
             expectImagesToBeTheSame(tempDir + '/small_test_result_0_0_0.png', 'spec/expected/small-test.png')
-            .then(done)
-            .catch(done.fail);
+                .then(done)
+                .catch(done.fail);
         });
     });
 

programming_language: JavaScript