Skip to content
Merged
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 @@ -7,6 +7,7 @@
* security: Move the graph 'Add to QuickTree' icon's inline `onClick='addQuickTree()'` handler into a delegated jQuery binding in `js/quicktree.js` (via a `quicktreeAddLink` class and `data-` attributes) and replace the confirmation pages' inline `onClick='cactiReturnTo()'` Cancel buttons with the CSP-safe `cactiReturnTo` class, so the pages no longer trip Cacti's Content-Security-Policy script-src-attr directive
* dev: Replace the translation-template CI check that regenerated locales/po/cacti.pot and compared it with a diff-based gate (tests/bin/check-i18n-pot.php) requiring cacti.pot to be updated only when a pull request adds, removes, or modifies an i18n function call
* dev: Measure CI coverage with xdebug instead of pcov so the plugin's own sources are instrumented (pcov auto-scopes to the Composer root and skipped cacti/plugins/, leaving the patch-coverage gate with nothing to measure)
* security: Normalize the requested location before building the breadcrumb URL so a crafted location value is not reflected into the navigation
* dev: Enforce patch coverage of changed lines in CI and remove the inert COMPOSER_ROOT_VERSION env from the Pest step
* security: Add a version-safe CSP nonce (`plugin_quicktree_csp_nonce()`) to every inline `<script>` tag so pages stay compatible with Cacti's Content-Security-Policy nonce enforcement, while falling back cleanly on older Cacti releases that lack the `CactiSecureHeaders` class
- issue: Quicktree continually registers a realm
Expand Down
4 changes: 3 additions & 1 deletion setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,12 @@ function quicktree_page_head(): void {
* added.
*/
function quicktree_draw_navigation_text($nav): array {
include_once(__DIR__ . '/includes/security.php');

$nav['quicktree.php:'] = [
'title' => __('QuickTree', 'quicktree'),
'mapping' => (get_nfilter_request_var('location') == 'console' ? 'index.php:' : ''),
'url' => 'quicktree.php?location=' . get_nfilter_request_var('location'),
'url' => 'quicktree.php?location=' . quicktree_normalize_location(get_nfilter_request_var('location')),
'level' => '1'
];

Expand Down
34 changes: 34 additions & 0 deletions tests/Unit/QuicktreeNavigationTextTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
*/

/*
* The breadcrumb URL is rendered into the page, so the request's location
* value must never reach it unnormalized.
*/

beforeAll(function () {
require_once __DIR__ . '/../../setup.php';
});

afterEach(function () {
$GLOBALS['__test_request_vars'] = array();
});

it('builds the breadcrumb from a normalized location', function ($location, $mapping, $url) {
$GLOBALS['__test_request_vars']['location'] = $location;

$nav = quicktree_draw_navigation_text(array());

expect($nav['quicktree.php:']['mapping'])->toBe($mapping);
expect($nav['quicktree.php:']['url'])->toBe($url);
})->with([
'console' => ['console', 'index.php:', 'quicktree.php?location=console'],
'tab' => ['tab', '', 'quicktree.php?location=tab'],
'hostile' => ['"><script>alert(1)</script>&action=clear', '', 'quicktree.php?location=tab'],
]);
Loading