hardening: migrate quicktree SQL helpers to prepared variants, adopt Pest test harness - #20
Merged
Merged
Conversation
Add targeted tests for prepared statement migration, output escaping, auth guard presence, CSRF token validation, redirect safety, and PHP 7.4 compatibility. Tests use source-scan patterns that verify security invariants without requiring the Cacti database. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
- remove composer.json (Pest/PHPUnit now come from Cacti core's vendor tree via CI) - import phpunit.xml, tests/bootstrap-unit.php, tests/TestCase.php, tests/.cacti-version, and tests/Pest.php from plugin_evidence, adapted for quicktree's source files - convert tests/test_prepared_statements.php and tests/test_form_wrapper.php from plain assert scripts into Pest tests (tests/Security/PreparedStatementsMigrationTest.php, tests/Unit/FormWrapperTest.php) - drop stale references to the removed plain-script test files from existing Pest specs - adapt .github/workflows/plugin-ci-workflow.yml from plugin_evidence to install/test the quicktree plugin
TheWitness
requested review from
bmfmancini and
xmacan
and
a lite review from Copilot
September 18, 2026 01:58
There was a problem hiding this comment.
🟡 Changes recommended
The redirect-safety tests fail against two redirects, and CI requests coverage without installing a coverage driver.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR hardens QuickTree database access and location handling while migrating all tests to Pest with a Cacti-provided test environment.
Changes:
- Converts selected SQL reads to prepared helpers.
- Adds location normalization and redirect-safety checks.
- Replaces standalone tests with Pest and updates CI integration.
File summaries
| File | Description |
|---|---|
.github/workflows/plugin-ci-workflow.yml |
Adds Cacti-based Pest CI |
phpunit.xml |
Configures the Pest suite |
quicktree.php |
Uses prepared queries and normalized locations |
quicktree_security.php |
Adds location normalization |
setup.php |
Uses prepared version lookup |
tests/bootstrap-unit.php |
Adds Cacti test bootstrap and stubs |
tests/TestCase.php |
Adds shared test base |
tests/Pest.php |
Adds Pest configuration |
tests/.cacti-version |
Defines expected Cacti version |
tests/Unit/* |
Adds unit coverage |
tests/Security/* |
Adds security and compatibility checks |
tests/Integration/* |
Adds redirect wiring checks |
tests/E2E/* |
Adds debug-header regression check |
tests/test_form_wrapper.php |
Replaced by Pest spec |
tests/test_prepared_statements.php |
Replaced by Pest spec |
composer.json |
Removed plugin-local dependency manifest |
Review details
Suppressed comments (2)
quicktree.php:324
- This redirect has the same termination problem: the switch
breakdoes not terminate the request, so RedirectSafetyTest fails and later code can run after the Location header. Add anexitimmediately after the redirect.
header('Location: quicktree.php?location=' . $location);
tests/Unit/FormWrapperTest.php:22
- These guarded declarations redefine Cacti's global UI functions while Pest is loading an individual spec. If Cacti or another spec has already declared one, the guard skips the stub and this test either records no events or invokes production behavior; move the configurable stubs into the shared bootstrap/fixture instead.
if (!function_exists('top_header')) {
function top_header() {
$GLOBALS['__form_wrapper_events'][] = 'top_header';
}
}
- Files reviewed: 21/21 changed files
- Comments generated: 8
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- quicktree.php: add missing exit after header(Location) redirects in the 'clear' and 'remove' actions, matching the existing pattern used elsewhere in the file (satisfies RedirectSafetyTest) - tests/Security/SetupStructureTest.php: check the INFO file for name/version keys instead of a nonexistent inline array in setup.php, since plugin_quicktree_version() reads the version from INFO via parse_ini_file rather than returning a literal array
- explicitly install the xdebug coverage driver in CI so --coverage-clover cannot silently fail on a runner without one - tests/Security/AuthGuardTest.php: assert the id request var is read via get_filter_request_var() directly instead of a vacuous check that never triggered - tests/Security/Php74CompatibilityTest.php: remove the no-op 'array() vs short syntax' test (short array syntax isn't a PHP 7.4 compatibility issue, and the test never asserted anything) - tests/Security/PreparedStatementConsistencyTest.php: tighten the interpolated-SQL heuristic to require zero matches, while excluding legitimate array(\) parameter binding from the check so it no longer flags safe prepared calls as false positives - tests/bootstrap-unit.php: make get_nfilter_request_var() configurable via \['__test_request_vars'], and move the shared top_header/form_start/html_start_box/html_end_box/form_end stubs here so they are declared exactly once instead of being guarded per-spec - tests/Unit/FormWrapperTest.php: use the configurable request var stub to exercise both the header-present and header-not-set branches of quicktree_action_form_begin() - quicktree_security.php: apply the standard GPL v2 header used by setup.php/quicktree.php - CHANGELOG.md: add a develop entry for the hardening and Pest test-harness migration
bmfmancini
approved these changes
Sep 18, 2026
2 tasks
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
Forks the changes from #12 (opened from an external fork) into a branch on the Cacti org's own fork tree, and adopts the Cacti-standard Pest test harness used by
plugin_evidence.plugin_quicktreeSQL helper reads to prepared variants (quicktree.php,setup.php)quicktree_security.phpwithquicktree_normalize_location()and use it for location handling / redirectscomposer.json— Pest/PHPUnit are now provided by Cacti core's Composer-managed vendor tree, installed by the CI workflow, matching theplugin_evidencepatternphpunit.xml,tests/bootstrap-unit.php,tests/TestCase.php,tests/.cacti-version, andtests/Pest.phpfromplugin_evidence, adapted to quicktree's own source files (quicktree.php,setup.php,quicktree_security.php,ui_helpers.php)tests/test_prepared_statements.php,tests/test_form_wrapper.php) into Pest specs (tests/Security/PreparedStatementsMigrationTest.php,tests/Unit/FormWrapperTest.php) — all test cases now run under Pest.github/workflows/plugin-ci-workflow.ymlfromplugin_evidenceto install/enable thequicktreeplugin and run the fulltests/suite through PestTests
php -lacross all plugin and test PHP filestests/(Security, Unit, Integration, E2E) via the updated CI workflowCloses #12