Skip to content

security: move inline event handlers to CSP-safe bindings - #38

Merged
TheWitness merged 2 commits into
mainfrom
fix/csp-inline-handlers
Oct 8, 2026
Merged

TheWitness merged 2 commits into
mainfrom
fix/csp-inline-handlers

Conversation

@TheWitness

@TheWitness TheWitness commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Removes the plugin's remaining inline event-handler attributes so pages comply with Cacti's Content-Security-Policy script-src-attr directive. Part of the fleet-wide CSP inline-handler cleanup.

Changes

  • setup.php (quicktree_graph_buttons hook) — the graph "Add to QuickTree" + icon moves its onClick='addQuickTree(...)' to a delegated jQuery binding, passing the ids via a quicktreeAddLink class and data-local-graph-id / data-rra-id attributes.
  • js/quicktree.js — adds the delegated click binding (quicktree.js is already injected on every page via the page_head hook, so it is present on the graph view).
  • quicktree.php — the two confirmation-page Cancel buttons switch from onClick='cactiReturnTo()' to the CSP-safe cactiReturnTo class.
  • tests/Unit/QuicktreeGraphButtonsTest.php — asserts the new data- attribute markup, the quicktreeAddLink binding class (the hook into the delegated handler), and that no inline on*= handler is emitted — so the test fails if either the binding class is dropped or an inline handler regresses. Keeps the measured setup.php hook at 100% patch coverage.
  • README.md / CHANGELOG.md — "Cacti compatibility" note + changelog entry.

No __esc()/i18n calls changed, so cacti.pot is untouched; quicktree.php is already in the patch-coverage allowlist.

Compatibility

Cacti 1.2.31+ binds the cactiReturnTo class automatically. The README documents a one-time applySkin() snippet for operators on earlier releases. No shim is baked into core or the plugin.

Cacti's Content-Security-Policy script-src-attr directive blocks inline
event-handler attributes. This converts the plugin's remaining inline
handlers:

- The graph "Add to QuickTree" icon (graph_buttons hook in setup.php) moves
  its onClick='addQuickTree(...)' to a delegated jQuery binding in
  js/quicktree.js, carrying the ids via a quicktreeAddLink class and
  data-local-graph-id / data-rra-id attributes.
- The two confirmation-page Cancel buttons in quicktree.php switch from
  onClick='cactiReturnTo()' to the CSP-safe cactiReturnTo class.

The graph_buttons unit test is updated to assert the new data-attribute
markup. Cacti 1.2.31+ binds the cactiReturnTo class automatically; the README
documents a one-time applySkin() snippet for earlier releases.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Cancel buttons break on supported Cacti 1.2.29–1.2.30 installations without manually patching core.

2 open findings
What changed in this PR

Moves QuickTree interactions to CSP-safe delegated bindings.

Changes:

  • Replaces inline graph and Cancel handlers.
  • Adds delegated QuickTree click handling.
  • Updates tests and compatibility documentation.
File Description
setup.php Emits data attributes for graph actions.
js/​quicktree.js Adds delegated graph-click handling.
quicktree.php Uses cactiReturnTo classes.
tests/​Unit/​QuicktreeGraphButtonsTest.php Updates graph-button assertions.
README.md Documents legacy Cacti compatibility.
CHANGELOG.md Records the CSP change.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread README.md
Comment thread tests/Unit/QuicktreeGraphButtonsTest.php
The graph-buttons test only checked the data- payload, so it would still pass if the quicktreeAddLink class (which the delegated click in js/quicktree.js keys off) were dropped, or if an inline onClick regressed. Assert the binding class is present and that no on*= attribute is emitted.

@TheWitness TheWitness left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

CSP cleanup looks correct and consistent with the fleet pattern: the graph + icon's inline onClick='addQuickTree(...)' moves to a delegated binding in js/quicktree.js keyed off the quicktreeAddLink class with data-local-graph-id / data-rra-id payloads, and the two confirmation-page Cancel buttons switch to the CSP-safe .cactiReturnTo class. quicktree.js is already injected on every page via the page_head hook, so the delegated handler is present on the graph view.

Open issue addressed (ec1e0cb)

The Copilot reviewer correctly noted that QuicktreeGraphButtonsTest only asserted the data- payload, so it would still pass if the quicktreeAddLink binding class were dropped (delegated click never runs) or if an inline handler regressed. Added two assertions: toContain('quicktreeAddLink') and not->toMatch('/on[a-z]+\s*=/i'). Thread resolved.

Verification

  • php -l clean on the test file.
  • Simulated the exact hook output and confirmed all assertions pass, the inline-handler guard catches a reintroduced onClick, and it does not false-match the real markup.

Note: Pest isn't vendored in the plugin clone (CI runs it against a full Cacti tree), so I validated the assertion logic standalone rather than running the suite locally — worth a green CI check before merge.

The other thread (README < 1.2.31 compat note) was already resolved by the author.

@TheWitness
TheWitness merged commit 52516c1 into main Oct 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants