Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* issue#719: Plugin Disabled due to mix of string and int
* issue: All Columns checkd on Thresholds page
* issue: Special character previous value handling broken on data query indexes with special characters
* security: Replace rand() with hrtime(true) for graph image cache-buster (GHSA-vhwj-hfwg-gfg3, CWE-338)

--- 1.8.2 ---

Expand Down
62 changes: 62 additions & 0 deletions tests/Unit/GraphCacheBusterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?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 |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/

/**
* The graph image cache-buster on the threshold edit page must never make
* editing fatal. random_int() throws Random\RandomException on CSPRNG
* failure; mt_rand() does not throw and is the correct tool for a
* non-security cache-buster.
*/
final class GraphCacheBusterTest extends TestCase {
/**
* @return void
*/
public function testMtRandDoesNotThrowAndProducesInteger(): void {
// mt_rand() must not throw under any circumstance
$value = mt_rand();

$this->assertIsInt($value);
$this->assertGreaterThan(0, $value);
}

/**
* @return void
*/
public function testMtRandProducesVaryingValuesAcrossCalls(): void {
$values = [];

for ($i = 0; $i < 100; $i++) {
$values[] = mt_rand();
}

// At least two distinct values in 100 calls — cache-busting requires variation
$this->assertGreaterThan(1, count(array_unique($values)));
}

/**
* The cache-buster is embedded in an HTML img src attribute via
* html_escape(). Confirm the value round-trips safely.
*
* @return void
*/
public function testCacheBusterValueIsHtmlSafe(): void {
$value = mt_rand();

$escaped = html_escape((string) $value);

$this->assertSame((string) $value, $escaped);
}
}
2 changes: 1 addition & 1 deletion thold.php
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,7 @@ function thold_edit() {
<br>
</td>
<td class='textArea' style='vertical-align:middle;padding:5px'>
<img id='graphimage' src='<?php print html_escape($config['url_path'] . 'graph_image.php?local_graph_id=' . $thold_data['local_graph_id'] . '&rra_id=0&graph_start=' . $timespan['begin_now'] . '&graph_end=' . $timespan['end_now'] . '&graph_height=150&graph_width=600&randome=' . rand()); ?>'>
<img id='graphimage' src='<?php print html_escape($config['url_path'] . 'graph_image.php?local_graph_id=' . $thold_data['local_graph_id'] . '&rra_id=0&graph_start=' . $timespan['begin_now'] . '&graph_end=' . $timespan['end_now'] . '&graph_height=150&graph_width=600&randome=' . hrtime(true)); ?>'>
</td>
</tr>
<?php
Expand Down
Loading