mirror of
https://github.com/Cacti/cacti.git
synced 2026-11-05 03:28:33 +09:00
substitute_script_path() now follows the template's own $(...) and backtick
command substitutions as nested parsing contexts with their own quote state, so a
token placed inside one ("$(printf %s <field>)") is judged against that fresh
context instead of a suspended outer double quote. This closes the
nested-reinterpretation bypass where an escaped value sitting inside a command
substitution could be re-activated by an outer double quote. Backslash pairing in
both the unquoted and double-quoted contexts now also neutralizes $ and backtick,
so an escaped command substitution (\$(...) or \`...`) is not mis-detected as live.
.github/workflows/pr-changed-coverage.yml: drop the hard-coded PR-number
allowlist so the job runs whenever the path filter selects it, rather than
silently skipping every unlisted PR once these merge.
tests/Unit/Security/ShellInjection/ScriptFieldShellRoundTripTest.php: skip when
either exec() or proc_open() is unavailable (the test launches the fixture with
exec() while the fixture itself uses proc_open()). The fixture adds 7 nested
command-substitution and backtick round-trip cases (90 -> 97), each proving the
field value echoes back verbatim with nothing inside it executing.
18 lines
894 B
PHP
18 lines
894 B
PHP
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2026 The Cacti Group |
|
|
| Licensed under the GNU General Public License, version 2 or later. |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
test('substituted shell fields retain literal values across quote and backslash contexts', function () {
|
|
$fixture = dirname(__DIR__, 3) . '/fixtures/Core/ScriptFieldShellRoundTrip.php';
|
|
$output = [];
|
|
$status = 0;
|
|
exec(escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg($fixture), $output, $status);
|
|
expect($status)->toBe(0);
|
|
$result = json_decode(implode("\n", $output), true, 512, JSON_THROW_ON_ERROR);
|
|
expect($result['passed'])->toBe(97);
|
|
})->skip(stripos(PHP_OS, 'WIN') === 0 || !function_exists('exec') || !function_exists('proc_open'), 'POSIX shell required');
|