Repository navigation
fix: repoint include/ -> includes/ plugin_hooks on every upgrade check so broken installs self-heal - #410
Merged
Conversation
The hook file repoint lived inside the version-change gate in intropage_upgrade_database(), so installs whose plugin_config.version was already bumped to the current version (but whose plugin_hooks rows were never repointed from the old include/ path) never got healed. With the old include/ directory still present this produced "Cannot redeclare ..." fatals from loading both include/functions.php and includes/functions.php; after deleting include/ it produced repeated "SECURITY ERROR: Attempted inclusion of invalid plugin file include/settings.php" because the stale hook rows point at a now-missing file. Run the idempotent repoint UPDATE unconditionally (before the version comparison) so broken installs self-heal on the next upgrade check. The WHERE ... file LIKE 'include/%' filter makes it a no-op on healthy installs. The duplicate copy inside the version gate is removed.
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The existing current-version lifecycle test will fail until updated for the new database call.
Review effort: Balanced
Findings: 1
What changed in this PR
Moves stale hook-path repair outside the version gate so broken installations self-heal.
Changes:
- Runs the
include/→includes/hook migration on every upgrade check. - Removes the gated duplicate.
| File | Description |
|---|---|
includes/database.php |
Makes hook-path repair unconditional. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
TheWitness
added a commit
to Cacti/plugin_evidence
that referenced
this pull request
Oct 1, 2026
The hook file repoint lived inside the version-change gate in plugin_evidence_upgrade_database(), so installs whose plugin_config.version was already bumped to the current version (but whose plugin_hooks rows were never repointed from the old include/ path) never got healed. With the old include/ directory still present this risks "Cannot redeclare ..." fatals from loading both include/<lib> and includes/<lib>; after deleting include/ it produces repeated "SECURITY ERROR: Attempted inclusion of invalid plugin file include/<lib>" because the stale hook rows point at a now-missing file. Run the idempotent repoint UPDATE unconditionally (before the version comparison) so broken installs self-heal on the next upgrade check. The WHERE ... file LIKE 'include/%' filter makes it a no-op on healthy installs. Mirrors the intropage fix (Cacti/plugin_intropage#410).
…e installs The repoint moved out of the version-change gate, so plugin_intropage_check_config() now issues the idempotent plugin_hooks UPDATE even when the stored version already matches. Update the lifecycle test to pin that contract (exactly one db call: the repoint) instead of asserting no work is done.
browniebraun
approved these changes
Oct 1, 2026
xmacan
approved these changes
Oct 1, 2026
TheWitness
added a commit
to Cacti/plugin_evidence
that referenced
this pull request
Oct 7, 2026
…k so broken installs self-heal (#55) * fix: repoint include/ -> includes/ plugin_hooks on every upgrade check The hook file repoint lived inside the version-change gate in plugin_evidence_upgrade_database(), so installs whose plugin_config.version was already bumped to the current version (but whose plugin_hooks rows were never repointed from the old include/ path) never got healed. With the old include/ directory still present this risks "Cannot redeclare ..." fatals from loading both include/<lib> and includes/<lib>; after deleting include/ it produces repeated "SECURITY ERROR: Attempted inclusion of invalid plugin file include/<lib>" because the stale hook rows point at a now-missing file. Run the idempotent repoint UPDATE unconditionally (before the version comparison) so broken installs self-heal on the next upgrade check. The WHERE ... file LIKE 'include/%' filter makes it a no-op on healthy installs. Mirrors the intropage fix (Cacti/plugin_intropage#410). * test: assert the include/ -> includes/ hook repoint runs on up-to-date installs The repoint moved out of the version-change gate, so plugin_evidence_check_config() now issues the idempotent plugin_hooks UPDATE even when the stored version already matches. Update the lifecycle test to pin that contract (exactly one db call: the repoint) instead of asserting no work is done.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Enabling intropage can fatal with a redeclaration, and after manually deleting the old
include/directory the data collector/UI then logs a flood ofSECURITY ERROR: Attempted inclusion of invalid plugin file include/settings.php from intropage with the hook name config_settings.Root cause
The plugin's library directory was renamed
include/->includes/.intropage_upgrade_database()already contains the migration that repoints staleplugin_hooksrows from the old path to the new one:…but it lives inside the
if (!cacti_version_compare($oldv, $current, '='))version gate. On an install whoseplugin_config.versionwas already bumped to the current version without its hooks having been repointed (e.g. the version write succeeded on an earlier load but the hooks were not, or the repoint shipped in a later commit of the same version number), the gate is permanently closed and the repoint never runs again.With the old
include/directory still on disk, the staleinclude/functions.phpand the newincludes/functions.phpboth get loaded in one request ->Cannot redeclare .... Once the user removesinclude/to escape that, the stale hook rows now point at a missing file and Cacti's plugin file-inclusion security check rejects every one -> the repeatedSECURITY ERRORlines.Fix
Run the idempotent hook repoint unconditionally, before the version comparison, so a broken install self-heals on the next upgrade check (which is reached via
plugin_intropage_check_config()/plugin_intropage_upgrade(), both invoked by Cacti core directly rather than through the broken hook rows). TheWHERE ... file LIKE 'include/%'filter makes it a no-op on healthy installs. The now-duplicate copy inside the version gate is removed.Validation
includes/database.phpchanges; the repoint moves out of the version gate, no other logic is touched.file LIKE 'include/%', so the extraUPDATEis a no-op.include/...): the repoint now runs, rewriting the rows toincludes/..., which clears both the redeclaration fatal and theSECURITY ERRORfloods on the next page load.Note: I was unable to run
php -lin this environment; the change is a straight hoist of an existing statement, reviewed by inspection.