* security: contain data source paths within the RRA directory (GHSA-9qff-xccr-rrc5)
* security: escape executable path in exec_background on non-win32 (GHSA-cv7j-p6fh-j4q7)
* security: stop disabled accounts authenticating via remember-me cookie and revoke on disable (GHSA-pqrp-v752-mc4f)
* security: prefer base_url over client Host for the force_https redirect (GHSA-3466-fp7g-c9rf)
* changelog: add fragments for GHSA-9qff-xccr-rrc5, GHSA-cv7j-p6fh-j4q7, GHSA-pqrp-v752-mc4f, GHSA-3466-fp7g-c9rf
* security: address review findings on GHSA batch 2 (develop)
- lib/dsstats.php, poller_maintenance.php: route through
get_data_source_path() instead of expanding data_source_path directly,
so the RRA containment check applies to these consumers too (GHSA-9qff)
- lib/functions.php: data_source_path_within_rra() now also validates
the realpath of each existing ancestor segment, closing a symlink
pivot that the purely lexical check missed (GHSA-9qff)
- include/global.php: fail closed instead of falling back to SERVER_NAME
when base_url is unset/invalid, removing the residual open-redirect
path (GHSA-3466)
- lib/html_utility.php: cacti_force_https_host()/
cacti_build_https_redirect_url() now parse a scheme-less base_url
(matching lib/reports.php's own normalization) and preserve a
configured non-default port instead of silently dropping it (GHSA-3466)
- tests: move DataSourcePathContainmentTest.php into
tests/Unit/Security/PathTraversal/, and switch its fixtures from a
fictional CACTI_PATH_RRA path to a real temp directory so the new
realpath()-based checks (including a symlink-pivot regression case)
can actually run
* test: fix CACTI_PATH_RRA constant collision in DataSourcePathContainmentTest
CI showed 2 failures: RrdProxyProtocolTest.php runs earlier in the same
Pest process and already defines CACTI_PATH_RRA to a fictional,
non-existent '/var/lib/cacti/rra', so our own definition guard never
ran and realpath(CACTI_PATH_RRA) returned false for every assertion,
failing the two tests that expect containment to be true.
Now ensure the directory backing CACTI_PATH_RRA actually exists on
disk regardless of who defined the constant first, and gracefully
skip only the fixture-dependent assertions if this process can't
create it (e.g. no permission on a system path).
* test: refresh sink inventory baseline for exec_background rename
5fbe90fb4 renamed \ to \ in lib/poller.php's
exec() calls (GHSA-cv7j-p6fh-j4q7) but never regenerated the tracked
sink inventory, so the 'sink and architectural hotspot guard' CI check
has been failing on this branch since that commit. Regenerated via
tests/security/build_sink_inventory.sh | tr -d '\r' | LC_ALL=C sort;
diff confirms only those two lines changed.
* fix: address CI failures on GHSA batch 2 (develop)
- lib/auth.php: verify the remember-me token before revoking a disabled
account's cache row, so a forged token no longer triggers a database
write (fixes AuthSystemRegressionIntegrationTest)
- apply php-cs-fixer coding standard fixes (comment style, phpdoc
alignment, list-to-short-array syntax) flagged by the locked
integration check
- refresh the architectural hotspots baseline for the exec_background
safe_filename rename
* fix: update PHPStan baseline for reordered check_auth_cookie and get_data_source_path
- lib/auth.php: reordering the disabled-account check after the token
match moved one 'enabled' offset access to a new line, bumping the
file's expected occurrence count from 3 to 4
- lib/functions.php: the GHSA-9qff-xccr-rrc5 containment log line reads
\['data_source_path'], a genuinely new array|bool access
not previously tracked
---------
Co-authored-by: copilot-swe-agent <copilot-swe-agent[bot]@users.noreply.github.com>