Files
cacti/tests/Unit/Security/Csrf/UpdatePolicyPostGuardTest.php
T
TheWitness 41e6d9e033 security: consolidate verified GHSA fixes for develop (batch 4) (#8145)
* security: consolidate verified GHSA fixes for develop (batch 4)

Develop counterparts of the 1.2.x batch-4 fixes in #8144, re-verified against
current develop HEAD.

- GHSA-4rmr-wvjq-qxc2: include/auth.php Basic Auth and guest branches fall
  through to the per-page realm check instead of returning early.
- GHSA-j67j-wpm4-9g3x: the pre-dispatch update_policy branch in user_admin.php
  and user_group_admin.php requires a CSRF-token POST. The denylist -> allowlist
  redesign is tracked for 1.3 in #8143.
- GHSA-2p3x-f5jm-rg6p: the View-Graphs -> poller RCE chain is broken by the
  realm check (4rmr), the update_policy guard (j67j) and shell-free webhits (x5pw).
- GHSA-x5pw-cg7j-mj4r: scripts/webhits.pl runs wc through a shell-free list-form open.
- GHSA-9737-rqh3-h7fh: names interpolated into raise_message() now use __esc()
  across the UI; URL- and HTML-bearing messages are excluded.
- GHSA-9x9h-2577-9w86: the colordropdown input is built as a node and the label
  is no longer round-tripped through parseHTML (the list item already used
  createTextNode on develop).
- GHSA-h96j-8xhc-2p3w: remote_agent.php authorizes on $_SERVER['REMOTE_ADDR'],
  not get_client_addr(), which honours client-settable proxy headers.

Regression guards under tests/Unit/Security/{Auth,Csrf,Xss,ShellInjection}.
php -l, check-changelog.py and the sink/architectural baselines all pass.

* chore: reference PR #8145 on the batch-4 1.3.0-dev CHANGELOG entries

* security: resolve develop merge - keep id-only xmlerror unescaped (matches #8141 h745 test)

* security(GHSA-j67j): use REQUEST_METHOD POST guard instead of raw \ (hardening-pattern-guard)

* security(GHSA-9737): fix review findings - drop double-encoding in __esc, escape missed name sinks, correct plugins format-arg count
2026-10-02 13:10:42 -04:00

37 lines
1.5 KiB
PHP

<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
*/
/*
* GHSA-j67j-wpm4-9g3x: the update_policy branch runs before the action
* dispatcher, so the global.php GET/CSRF denylist cannot cover it. Both
* user_admin.php and user_group_admin.php must require a POST before calling
* update_policies() (csrf_check() only validates the token on POST).
*/
$root = dirname(__DIR__, 4);
test('update_policy requires a POST before mutating the policy', function () use ($root) {
foreach (array('/user_admin.php', '/user_group_admin.php') as $file) {
$source = file_get_contents($root . $file);
$branch = strpos($source, "if (isrv('update_policy')) {");
$call = strpos($source, 'update_policies();', $branch);
$guard = strpos($source, "strtoupper(\$_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST'", $branch);
expect($branch)->not->toBeFalse()
->and($call)->not->toBeFalse()
->and($guard)->not->toBeFalse()
->and($guard)->toBeLessThan($call);
$pre = substr($source, $guard, $call - $guard);
expect($pre)->toContain('http_response_code(405)')
->and($pre)->toContain('exit;');
}
});