mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-30 00:26:50 +09:00
* chore: resolve concurrent CHANGELOG appends with a union merge Every PR lands on the same two anchors, so merging one reliably conflicts the others on CHANGELOG alone. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> (cherry picked from commit6bc8e63ecb) * feat(changelog): take entries as fragment files instead of CHANGELOG edits Every pull request edited one of two lines, so merging one conflicted the rest. A file per change gives concurrent PRs nothing to collide over. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> (cherry picked from commita8a0bfa29a) * chore(security): drop line numbers from the tracked sink baselines Both verifiers already strip the line before comparing, so the tracked numbers carried no signal and rewrote 212 lines of baseline on any edit that shifted code, conflicting every open pull request. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> (cherry picked from commitccfd3d374b) * fix(ci): rebase stale pull request branches instead of merging them A merge update adds a commit per run, so branches accumulate snapshots of old develop and re-conflict on every shared file they carry. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> (cherry picked from commite9e33c77cd) * test: match the escaping call rather than the exact source line The literal assertions here required the uncast form while PhpBinaryPathNullCoercionTest required the cast, so the two could not both pass and whichever landed second broke the other. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> (cherry picked from commit98cfc84756) * fix(changelog): handle security entries in fragments and validation Review caught the missing type. Security entries also take GHSA identifiers and open a release section ahead of issue and feature entries, none of which the first pass handled. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: require Composer-managed dependencies Prevent agents from committing third-party package trees and require composer.json plus composer.lock updates instead. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
53 lines
2.7 KiB
PHP
53 lines
2.7 KiB
PHP
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2026 The Cacti Group |
|
|
| |
|
|
| This program is free software; you can redistribute it and/or |
|
|
| modify it under the terms of the GNU General Public License |
|
|
| as published by the Free Software Foundation; either version 2 |
|
|
| of the License, or (at your option) any later version. |
|
|
+-------------------------------------------------------------------------+
|
|
| Cacti: The Complete RRDtool-based Graphing Solution |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
/*
|
|
* Regression test for issue#7469.
|
|
*
|
|
* test_data_source()'s two script-server branches interpolated
|
|
* path_php_binary, an admin-set Settings > Paths value, into a command handed
|
|
* to shell_exec(). release/1.2.31 wrapped it in cacti_escapeshellcmd(); the
|
|
* fix never reached develop, leaving authenticated command injection in both
|
|
* the PHP_SCRIPT_SERVER and QUERY_SCRIPT_SERVER paths.
|
|
*/
|
|
|
|
require_once dirname(__DIR__, 3) . '/Helpers/CactiStubs.php';
|
|
require_once dirname(__DIR__, 4) . '/include/global.php';
|
|
|
|
$source = file_get_contents(__DIR__ . '/../../../../lib/functions.php');
|
|
|
|
test('the script-server branch escapes path_php_binary', function () use ($source) {
|
|
// Match the call rather than the exact source line. The cast is optional
|
|
// here because PhpBinaryPathNullCoercionTest owns whether it is present;
|
|
// asserting it in both places made the two tests contradict each other.
|
|
expect($source)->toMatch('/\$php\s*=\s*cacti_escapeshellcmd\(\s*(?:\(string\)\s*)?read_config_option\(\s*\'path_php_binary\'\s*\)\s*\)\s*;/')
|
|
->and($source)->not->toMatch('/\$php\s*=\s*read_config_option\(\s*\'path_php_binary\'\s*\)\s*;/');
|
|
});
|
|
|
|
test('the query-script-server branch escapes path_php_binary', function () use ($source) {
|
|
expect($source)->toMatch('/\$script_path\s*=\s*cacti_escapeshellcmd\(\s*(?:\(string\)\s*)?read_config_option\(\s*\'path_php_binary\'\s*\)\s*\)\s*\.\s*\' -q \'/')
|
|
->and($source)->not->toMatch('/\$script_path\s*=\s*read_config_option\(\s*\'path_php_binary\'\s*\)\s*\.\s*\' -q \'/');
|
|
});
|
|
|
|
test('escaping neutralizes a shell metacharacter in path_php_binary', function () {
|
|
$evil = 'php ; touch /tmp/pwned ; echo';
|
|
|
|
$cmd = cacti_escapeshellcmd($evil) . ' -q /tmp/script.php';
|
|
|
|
// escapeshellcmd backslash-escapes the ; so it can no longer start a
|
|
// new command; the injected touch never runs as its own statement.
|
|
expect($cmd)->not->toMatch('/(^|[^\\\\]);\s*touch/')
|
|
->and($cmd)->toContain('\;');
|
|
});
|