Подтвердить что ты не робот

Как избежать строки для команды оболочки в node?

В nodejs единственный способ выполнения внешних команд - через sys.exec(cmd). Я бы хотел вызвать внешнюю команду и передать ее через stdin. В nodejs пока еще нет способа открыть команду, а затем нажимать на нее данные (только для exec и получения ее стандартных выходов + ошибок), поэтому, похоже, единственный способ, которым я должен это сделать прямо сейчас, - это с помощью одной строковой команды, такой как:

var dangerStr = "bad stuff here";
sys.exec("echo '" + dangerStr + "' | somecommand");

Большинство ответов на такие вопросы были сосредоточены на любом регулярном выражении, которое не работает для меня в nodejs (которое использует механизм Javascript Google V8) или собственных функций с других языков, таких как Python.

Мне бы хотелось избежать опасностиStr, чтобы было безопасно составить строку exec, подобную приведенной выше. Если это поможет, опасностьStr будет содержать данные JSON.

4b9b3361

Ответ 1

Существует способ записи во внешнюю команду: process.createChildProcess (документация) возвращает объект с помощью метода write. createChildProcess не так удобен, потому что он не выполняет буферизацию stdout и stderr, поэтому вам понадобятся обработчики событий для чтения вывода в кусках.

var stdout = "", stderr = "";
var child = process.createChildProcess("someCommand");

child.addListener("output", function (data) {
    if (data !== null) {
        stdout += data;
    }
});
child.addListener("error", function (data) {
    if (data !== null) {
        stderr += data;
    }
});
child.addListener("exit", function (code) {
    if (code === 0) {
        sys.puts(stdout);
    }
    else {
        // error
    }
});

child.write("This goes to someCommand stdin.");

Ответ 2

Это то, что я использую:

var escapeShell = function(cmd) {
  return '"'+cmd.replace(/(["\s'$`\\])/g,'\\$1')+'"';
};

Ответ 3

Если вам нужно простое решение, вы можете использовать это:

function escapeShellArg (arg) {
    return `'${arg.replace(/'/g, `'\\''`)}'`;
}

Таким образом, ваша строка будет просто экранирована одиночными кавычками, о которых говорил Крис Джонсен.

echo 'John'\' phone';

Он работает в bash из-за сильного цитирования, похоже, что он также работает в fish, но не работает в zsh и sh.

Если у вас bash, вы можете запустить script в sh или zsh с помощью 'bash -c \'' + escape('all-the-rest-escaped') + '\''.

Но на самом деле... node.js избавит вас от всех необходимых символов:

var child = require('child_process')
  .spawn('echo', ['`echo 1`;"echo $SSH_TTY;\'\\0{0..5}']);

child.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

child.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

этот блок кода выполнит:

echo '`echo 1`;"echo $SSH_TTY;'\''\\0{0..5}'

и выведет:

stdout: `echo 1`;"echo $SSH_TTY;\'\\0{0..5}

или некоторая ошибка.

Взгляните на http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

Кстати, простое решение для запуска пула команд:

require('child_process')
  .spawn('sh', ['-c', [
    'cd all/your/commands',
    'ls here',
    'echo "and even" > more'
  ].join('; ')]);

Приятного дня!

Ответ 4

Вы никогда не должны полагаться на экранирование неизвестного ввода, идущего на параметр оболочки - почти всегда будет какой-то крайний случай, о котором вы не подумали, что позволяет пользователю выполнять произвольный код на вашем сервере.

Узел имеет поддержку вызова команды и передачи каждого аргумента отдельно, без необходимости экранирования. Это самый безопасный способ сделать это:

const { spawn } = require('child_process');
// Note that the arguments are in an array, not using string interpolation
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log('stdout: ${data}');
});

ls.stderr.on('data', (data) => {
  console.log('stderr: ${data}');
});

ls.on('close', (code) => {
  console.log('child process exited with code ${code}');
});

Документация здесь

Ответ 5

Вариант ответа Сильвена:

var escapeShell = function(string) {
    // Sanitise all space (newlines etc.) to a single space
    string.replace(/\s+/g, " ");
    // Optionally remove leading and trailing space
    string.replace(/^\s+|\s+$/g, " ");
    // Quote with single quotes, escaping backslashes and single quotes
    return "'" + string.replace(/(['\\])/g, '\\$1') + "'";
};

В предположении, что $ не нужно экранировать в одной кавычки (как указал Алекс), а другие типы цитат тоже не должны быть.

Ответ 6

Если вам также необходимо иметь дело со специальным символом (разрывы строк и т.д.), вы можете сделать это следующим образом:

str = JSON.stringify(str)
    .replace(/^"|"$/g,'') //remove JSON-string double quotes
    .replace(/'/g, '\'"\'"\'') //escape single quotes the ugly bash way

Предполагается, что вы используете Bash сильное цитирование с помощью одиночных кавычек), и получатель может понять, как экранирование JSON C-типа.