From d48115c21dfc4510ec65e65841e2cfe57b2034bb Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 13:42:53 +0000 Subject: [PATCH] bug: fix command injection in todo image identify (CWE-78) --- routes/index.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/routes/index.js b/routes/index.js index 6b5455f03e4..65514df8f54 100644 --- a/routes/index.js +++ b/routes/index.js @@ -9,6 +9,7 @@ var streamBuffers = require('stream-buffers'); var readline = require('readline'); var moment = require('moment'); var exec = require('child_process').exec; +var execFile = require('child_process').execFile; var validator = require('validator'); // zip-slip @@ -149,6 +150,21 @@ function parse(todo) { return t; } +function isSafeImageUrl(url) { + if (typeof url !== 'string' || /[\s\r\n]/.test(url)) { + return false; + } + + var parsed; + try { + parsed = new URL(url); + } catch (e) { + return false; + } + + return parsed.protocol === 'http:' || parsed.protocol === 'https:'; +} + exports.create = function (req, res, next) { // console.log('req.body: ' + JSON.stringify(req.body)); @@ -158,12 +174,15 @@ exports.create = function (req, res, next) { var url = item.match(imgRegex)[1]; console.log('found img: ' + url); - exec('identify ' + url, function (err, stdout, stderr) { - console.log(err); - if (err !== null) { - console.log('Error (' + err + '):' + stderr); - } - }); + if (isSafeImageUrl(url)) { + execFile('identify', [url], function (err, stdout, stderr) { + if (err !== null) { + console.log('Error (' + err + '):' + stderr); + } + }); + } else { + console.log('skipping identify for unsupported url'); + } } else { item = parse(item);