From 86085144712919dd0d75ef263ac60540635df3a9 Mon Sep 17 00:00:00 2001 From: TheWitness Date: Wed, 7 Oct 2026 17:38:25 -0400 Subject: [PATCH 1/3] security: move map navigation handlers to CSP-safe bindings Cacti's Content-Security-Policy script-src-attr directive blocks inline event-handler attributes. The map region navigation's "Start Over" and "Print" buttons (gpsmap_render_region in includes/polling/processregion.php) used inline onclick="window.location.reload(true)" and onclick="window.open('print.php')" handlers. They now carry gpsmapStartOver / gpsmapPrint classes and are wired via delegated jQuery bindings in js/GPSMaps.js, which is already included on every page via the page_head hook. No i18n calls changed, so cacti.pot is untouched. --- CHANGELOG.md | 1 + includes/polling/processregion.php | 4 ++-- js/GPSMaps.js | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cce3f19..0ef0094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Changelog --- develop --- +* security: Move the map region navigation's 'Start Over' and 'Print' buttons from inline `onclick` handlers to delegated jQuery bindings in `js/GPSMaps.js` (via `gpsmapStartOver`/`gpsmapPrint` classes) so the map no longer trips 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 * refactor: Switch every file inclusion from include/include_once to require/require_once for fail-fast consistency (schema already lives in includes/setup/database.php via the plugin table API, so no schema changes were needed) * 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) diff --git a/includes/polling/processregion.php b/includes/polling/processregion.php index 9a32250..1b01e63 100644 --- a/includes/polling/processregion.php +++ b/includes/polling/processregion.php @@ -527,8 +527,8 @@ function gpsmap_render_region(array $hostArrays, string $subnet, ?GpsmapPollStat // print out the information we have gathered. $body .= '
'; - $body .= '
'; - $body .= ''; + $body .= '
'; + $body .= ''; $body .= '
'; // six links per column block diff --git a/js/GPSMaps.js b/js/GPSMaps.js index 92bd3e2..6be6597 100644 --- a/js/GPSMaps.js +++ b/js/GPSMaps.js @@ -359,3 +359,17 @@ var gpsmap = { } } }; + +jQuery(function() { +jQuery(document).off('click.gpsmapNav', '.gpsmapStartOver') +.on('click.gpsmapNav', '.gpsmapStartOver', function(event) { +event.preventDefault(); +window.location.reload(true); +}); + +jQuery(document).off('click.gpsmapNav', '.gpsmapPrint') +.on('click.gpsmapNav', '.gpsmapPrint', function(event) { +event.preventDefault(); +window.open('print.php'); +}); +}); \ No newline at end of file From 2067ede67df51bcfeeb8583d8cd1c1ae496bb299 Mon Sep 17 00:00:00 2001 From: TheWitness <1439914+TheWitness@users.noreply.github.com> Date: Wed, 7 Oct 2026 18:28:27 -0400 Subject: [PATCH 2/3] test: cover the CSP-safe region navigation buttons Adds an expect()-based test that renders gpsmap_render_region() and asserts the Start Over/Print controls use delegated jQuery classes (gpsmapStartOver/gpsmapPrint) with no inline onclick. Satisfies the changed-line coverage gate for processregion.php, which the existing assert_*-helper tests (flagged risky) do not record. --- tests/Integration/RegionMenuCspTest.php | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/Integration/RegionMenuCspTest.php diff --git a/tests/Integration/RegionMenuCspTest.php b/tests/Integration/RegionMenuCspTest.php new file mode 100644 index 0000000..673d61f --- /dev/null +++ b/tests/Integration/RegionMenuCspTest.php @@ -0,0 +1,39 @@ +toBeTrue(); + + $menu = file_get_contents($root . '/plugins/gpsmap/XML/198.51.100-top.html'); + + expect($menu)->toContain('class="gpsmapStartOver"'); + expect($menu)->toContain('class="print gpsmapPrint"'); + expect($menu)->not->toContain('onclick'); +}); From d11946a7aaa5217aa380cfb1f1a958161e7aa42e Mon Sep 17 00:00:00 2001 From: TheWitness Date: Wed, 7 Oct 2026 18:39:16 -0400 Subject: [PATCH 3/3] js: indent region-nav bindings and use \ shorthand Addresses review feedback: indent the chained delegated click bindings and their callback bodies to reflect nesting, convert jQuery() to the \ shorthand, and add a trailing newline. --- js/GPSMaps.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/js/GPSMaps.js b/js/GPSMaps.js index 6be6597..017091c 100644 --- a/js/GPSMaps.js +++ b/js/GPSMaps.js @@ -360,16 +360,16 @@ var gpsmap = { } }; -jQuery(function() { -jQuery(document).off('click.gpsmapNav', '.gpsmapStartOver') -.on('click.gpsmapNav', '.gpsmapStartOver', function(event) { -event.preventDefault(); -window.location.reload(true); -}); +$(function() { + $(document).off('click.gpsmapNav', '.gpsmapStartOver') + .on('click.gpsmapNav', '.gpsmapStartOver', function(event) { + event.preventDefault(); + window.location.reload(true); + }); -jQuery(document).off('click.gpsmapNav', '.gpsmapPrint') -.on('click.gpsmapNav', '.gpsmapPrint', function(event) { -event.preventDefault(); -window.open('print.php'); + $(document).off('click.gpsmapNav', '.gpsmapPrint') + .on('click.gpsmapNav', '.gpsmapPrint', function(event) { + event.preventDefault(); + window.open('print.php'); + }); }); -}); \ No newline at end of file