* fix(a11y): [develop] correct labels, document semantics and duplicate IDs
Associates form controls with their labels, replaces obsolete tt markup, removes duplicate element IDs, and adds a native accessibility browser suite with its database fixture.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(a11y): validate label IDs and recognize attribute escaping
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* security: consolidate GHSA batch 11 fixes for develop (fq9x, hh7r, v99q, f5f5)
Mirrors the 1.2.x batch-11 security consolidation. Items already fixed on the
develop tip are credited on their advisories and omitted here:
- GHSA-54hx-hxc4-jq7j: TICK/SHIFT values already pass through strip_alpha().
- GHSA-hh7r CSV portion: already guarded via cacti_csv_cell(); only the
Content-Disposition filename needed sanitizing (included below).
- GHSA-mx5c: REST scaffold already deny-by-default (404 unless api_enabled),
enforced by tests/Unit/ApiDenyByDefaultTest.php.
- GHSA-rjvj/pjq5/fmhq/mfw8: already addressed on develop.
Fixes applied here:
- GHSA-fq9x-x3vf-3vf2 (High): add substitute_script_path() single-pass token
substitution and refactor get_full_script_path()/get_full_test_script_path()
to use a pre-escaped value map, closing the second-order re-substitution OS
command injection.
- GHSA-hh7r-464j-rf39: sanitize the Content-Disposition filename in graph_xport.php.
- GHSA-v99q-57w7-mpmg: escape the page title rendered in the HTML <title>.
- GHSA-f5f5-h85v-6m3h: render user admin tooltip content as escaped text.
* security: add batch-11 consolidation regression tests for develop
Addresses PR #8165 review feedback by adding regression coverage for all four fixed sinks:
- GHSA-fq9x: behavioral single-pass proof that substitute_script_path() does not re-substitute a field value containing another field token, plus source guards that both path builders use the helper.
- GHSA-hh7r: Content-Disposition filename strips CR/LF/quote/backslash.
- GHSA-v99q: the HTML <title> is html_escape()'d.
- GHSA-f5f5: both the user_admin.php and user_group_admin.php tooltips render data-tooltip as escaped text.
* style: apply php-cs-fixer formatting to substitute_script_path (CI coding standards)
* docs: require composer run-script php-cs-fixit before creating any pull request
* docs: require PHPStan (level 8, satisfies Level 6 floor) to pass before creating any pull request
---------
Co-authored-by: Larry Adams <TheWitness@users.noreply.github.com>
* security: consolidate verified GHSA fixes for develop (batch 4)
Develop counterparts of the 1.2.x batch-4 fixes in #8144, re-verified against
current develop HEAD.
- GHSA-4rmr-wvjq-qxc2: include/auth.php Basic Auth and guest branches fall
through to the per-page realm check instead of returning early.
- GHSA-j67j-wpm4-9g3x: the pre-dispatch update_policy branch in user_admin.php
and user_group_admin.php requires a CSRF-token POST. The denylist -> allowlist
redesign is tracked for 1.3 in #8143.
- GHSA-2p3x-f5jm-rg6p: the View-Graphs -> poller RCE chain is broken by the
realm check (4rmr), the update_policy guard (j67j) and shell-free webhits (x5pw).
- GHSA-x5pw-cg7j-mj4r: scripts/webhits.pl runs wc through a shell-free list-form open.
- GHSA-9737-rqh3-h7fh: names interpolated into raise_message() now use __esc()
across the UI; URL- and HTML-bearing messages are excluded.
- GHSA-9x9h-2577-9w86: the colordropdown input is built as a node and the label
is no longer round-tripped through parseHTML (the list item already used
createTextNode on develop).
- GHSA-h96j-8xhc-2p3w: remote_agent.php authorizes on $_SERVER['REMOTE_ADDR'],
not get_client_addr(), which honours client-settable proxy headers.
Regression guards under tests/Unit/Security/{Auth,Csrf,Xss,ShellInjection}.
php -l, check-changelog.py and the sink/architectural baselines all pass.
* chore: reference PR #8145 on the batch-4 1.3.0-dev CHANGELOG entries
* security: resolve develop merge - keep id-only xmlerror unescaped (matches #8141 h745 test)
* security(GHSA-j67j): use REQUEST_METHOD POST guard instead of raw \ (hardening-pattern-guard)
* security(GHSA-9737): fix review findings - drop double-encoding in __esc, escape missed name sinks, correct plugins format-arg count
* feat(auth): automatic User Group assignment from Login Provider groups
Add per-Login-Provider "Auto Assignment" rules to the User Group editor so a
user is added to (or removed from) a Cacti User Group at every login based on
the groups their Login Provider reports.
User Group editor (user_group_admin.php):
- Add General / Auto Assignment / Rights spacers to the General tab and rename
"General Group Options" to "Group Options".
- Render one text field per eligible Login Provider under Auto Assignment
(label = provider name). The admin enters a plain Group Name (e.g.
"Cacti Admins"), never a DN.
- Store the rules as JSON in the new user_auth_group.auto_assignments column,
keyed by login_providers.id.
Group resolution:
- SAML2 and OpenID match the configured name against the group attribute /
group claim values.
- LDAP/AD resolve membership live against the directory using a raw group name
plus the Search Base, trying AD (memberOf + nested LDAP_MATCHING_RULE_IN_CHAIN),
FreeIPA / 389 DS (groupOfNames/groupOfUniqueNames) and RFC2307 posixGroup
shapes so one plain name works everywhere. This requires a directory-read
bind, so the field is only offered for Anonymous Searching or Specific
Searching with a stored service account.
- A directory that cannot be reached returns "undetermined" so existing
memberships are left untouched rather than revoked on a transient outage.
Lifecycle:
- auto_assignments is reconciled on every login (lib/auth.php credential flow
and login_sso.php redirect flow).
- Deleting a Login Provider strips its key from every group's auto_assignments.
Schema: add user_auth_group.auto_assignments (cacti.sql + 1_3_0 upgrade).
* ci: document free-text group-name validateInput for constraint ratchet
* fix(auth): address PR review on automatic User Group assignment
- LDAP: add an Active Directory bare-name query (objectClass=group with the
member:1.2.840.113556.1.4.1941 nested-membership rule) so a plain group
name resolves on AD, which neither the posixGroup nor groupOfNames probe
could match.
- LDAP: make single-group membership tri-state and propagate an "undetermined"
result, so a search that fails after binding (timeout/dropped connection) no
longer looks like confirmed non-membership and revokes assignments.
- SAML2/OpenID: supportsAutoAssignment() now requires a configured group
claim, and applyAutoAssignments() skips any provider that is not currently
capable, so a blank claim can never strip users from their groups.
- Only reset the permission cache when a membership row actually changed
(accumulate db_affected_rows) rather than on every login that has a rule.
- Add unit tests for the reconciliation boundaries (add / remove / no-op /
incapable / undetermined) and for the LDAP group-query construction
(AD plain + nested, posixGroup, groupOfNames, DN mode).
- Regenerate locales/po/cacti.pot for the new UI strings.
* fix(phpstan): resolve level-8 errors from auto group assignment
- Guard supportsAutoAssignment() behind an instanceof AbstractLoginProvider
check so it is not called on the base LoginProviderInterface.
- Assign the injected field list to a variable (inject_form_variables takes it
by reference) and pass an is_array-guarded group row.
- Bump the lib/ldap.php ldap_get_entries baseline count 3->6 for the three new
group-membership query helpers.
* feat(validator): add settings constraint validation pilot
Routes saved settings through Symfony Validator so include/global_settings.php
can declare per-setting constraints inline. The save handler runs one
validator pass and surfaces violations via the existing raise_message()
pattern, replacing scattered ad-hoc checks. Pilot covers 12 high-value
settings; the rest stay on the existing implicit form-render checks.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(infection): allow infection/extension-installer composer plugin
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs(validator): document must-be-posted-to-validate contract
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(bootstrap): guard Symfony autoload in global_settings before use declarations
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(test): remove redundant autoload require in CactiSettingsTest
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(test): restore require_once for CactiSettings (not in Composer autoload)
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* feat(validator): fold helper into settings pilot
* fix(validator): translate default Symfony constraint messages
Default Symfony NotBlank/Length/Range/Choice/Positive messages render
in English regardless of Cacti locale because the validator runs
without a Symfony Translator. Pass explicit __()-wrapped message,
minMessage, maxMessage, and notInRangeMessage options on each bare
constraint in include/global_settings.php so violations participate
in Cacti's gettext pipeline. Documents the no-Translator decision in
CactiValidator so future contributors know to translate at the call
site.
Addresses Copilot PR #7077 review feedback.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(graph): improve remote agent parsing and RRD path validation
* feat(validator): migrate automation_graph_rules.php to symfony validator
* refactor(validator): move automation validator helper to shared library and enhance tests
* feat(validator): migrate automation_networks.php to symfony validator
* feat(validator): migrate automation_snmp.php to symfony validator
* feat(validator): migrate automation_templates.php to symfony validator
* feat(validator): migrate automation_tree_rules.php to symfony validator
* refactor(automation): move api_networks_save to shared library for testability
* feat(validator): add validateInput helper and migrate color_templates.php
* feat(validator): migrate host_templates.php to symfony validator
* feat(validator): migrate graph_templates.php to symfony validator
* feat(validator): migrate data_templates.php to symfony validator
* feat(validator): migrate data_input.php to symfony validator
* feat(validator): migrate data_queries.php to symfony validator
* feat(validator): migrate graphs_new.php to symfony validator
* feat(validator): migrate graphs.php to symfony validator
* feat(validator): migrate data_sources.php to symfony validator
* feat(validator): migrate user_group_admin.php to symfony validator
* feat(validator): migrate managers.php to symfony validator
* feat(validator): migrate package_repos.php to symfony validator
* Refactor pollers.php to use CactiValidator
* fix(security): close validator migration regressions
* test(snmp): add spine docker harness
* fix(review): address validator migration feedback
* fix(deps): include validator runtime packages
* chore(deps): normalize composer.json require-block indentation
The validator migration introduced tab-indented entries in an otherwise
space-indented require block. Re-indent the stevenmaguire/* and symfony/*
lines to 8 spaces so the block is consistent.
Co-Authored-By: Oz <oz-agent@warp.dev>
* fix(graphs): repair graph json response branch
* fix(validation): apply php cs fixer
* ci(codeql): skip autobuild for interpreted scans
* fix(link): satisfy phpstan path guard
* chore(pr): remove branch pollution
* ci(codeql): align autobuild pin with init and analyze
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* refactor(automation): use CactiValidator::validateInput, drop wrapper
automation_validate_input() in lib/api_automation.php was a byte-for-byte
duplicate of CactiValidator::validateInput() (identical session handling and
raise_message() semantics, and it already delegated to CactiValidator::validate
internally). Per review feedback, use the shared class directly everywhere
instead of a parallel automation-only wrapper.
- Remove automation_validate_input() from lib/api_automation.php
- Replace all call sites with CactiValidator::validateInput()
(automation_templates/graph_rules/tree_rules/snmp and api_networks_save)
- Update the automation validator unit tests to match
- Add @param/@return PHPDoc to CactiValidator specific-validator methods
Co-Authored-By: Oz <oz-agent@warp.dev>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Thomas Vincent <thomas@vincent.dev>
Co-authored-by: Oz <oz-agent@warp.dev>
Co-authored-by: TheWitness <thewitness@cacti.net>
user_domains, user_group_admin, user_log and the poller-cache view in
utilities concatenated the raw sort_column/sort_direction request vars
into ORDER BY, bypassing the get_order_string() allow-list. Route them
through sanitize_sql_column() and the strtoupper(...) === 'DESC' ternary,
matching the existing html_reports.php handling.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* Fix#6539 - Allow Standard Cacti Log Files to be Rotated on Demand from the Cacti UI
* QA: php-cs-fixer updates and documentation for lib/database.php
* QA: Update .gitignore for composer files
* QA: Update .gitignore for composer files
* QA: Back off .gitignore change its duplicated
* QA: Fix typing of db_has_permissions
* QA: Fixing typing issue in db_format_index_create
* Update lib/clog_webapi.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* QA: Fix additional code issues
* QA: Applying more defaults to add device
* QA: Fix at the database layer
* QA: Fixes based upon automated testing
* QA: Fix at the database layer
* QA: After new SQL checking
* QA: Skip MacTrack oui database download warnings
* QA: Fixing type issue
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Some minor changes to avoid errors in testing
* QA: Unused variable
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Minor introduced code defect
* QA: Adding some unifying space around concatination
* QA: Consistent comments and new function alias'
* QA: Multi-line comment corrections
* QA: Fix SQL Style
* QA: Missed one function alias
* QA: PHPStan Level 2 and PHPDoc fixes
* QA: PHPStan Level 2 and PHPDoc Fixes
* QA: PHPStan Level 6 Fixes
* QA: Fix lib/xml.php to PHPStan Level 6
* QA: Wrong grep -v
* PHPStan Level 6 for lib/vdef.php
* PHPStan Level 8 for lib/time.php
* QA: Raise PHPStan to Level 6 for lib/database.php
* QA: Remove @deprecated tag from grv()
* QA: Switch to htmle() alias over html_escape()
* QA: More addressing PHPStan issues at Level 6
* QA: Change recommended by Copilot for Readability
* QA: More PHPStan fixes
* QA: More PHPStan fixes
* QA: More PHPStan fixes for lib/utility.php
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Some phpseclib3 fixups to update to latest
* QA: More fixups for graphing for magic strings
* QA: More PHPStan fixes at Level 6
* QA: Fixing order string type on get_allowed_graphs()
* QA: Fixing improper use of print
* QA: Optimization of color_templates
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Raise PHPStan to Level 6 More Functions
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues testing Cacti
* QA: Copilot recommendation
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: Installer failing
* Undo ownership changes to remove tar errors
* QA: Updates after php-cs-fixer
* QA: Adding code checks to syntax checking
* QA Change syntax flow language
* QA: Reduce the number of cures
* QA: Use sequentional option
* Change runner to self-hosted for check job
* Fix typo in OS version in workflow file
* Add Git installation step in workflow
Added step to install Git if not already installed.
* Add '-y' flag to apt-get install and update commands
Updated apt-get commands to include '-y' for automatic confirmation.
* Change workflow OS version to 'ubuntu-latest'
Updated the workflow to use 'ubuntu-latest' instead of 'ubuntu:latest' and modified the 'runs-on' configuration.
* Remove sequential option from phpcsfixer script
* Remove PHPCS fixer step from workflow
Removed PHP coding standards check from workflow.
* Move code checks to before plugins
Moving these core checks to before the plugins are installed as we really want to check only the base Cacti here.
* Add Composer validation and caching to start of workflow
* QA: Addressing PHPStan additional
* QA: Restore composer lock file
* QA: Addressing PHPStan additional
* QA: Addressing PHPStan additional
* QA: Complete LDAP Project
* QA: php-cs-fixer doing it's thing
* QA: Syntax is already happening in PHPStan
* QA: The md5 function no longer exists
* QA: Update after ldap changes
* QA: Undo that last password hack
* QA: Attempting to switch to MariaDB 11.8
* QA: Attempting to switch to MariaDB 11.8
* QA: Resolving some issues with PHP8.4
* QA: Resolving some issues with PHP8.4
* QA: Add PHP8.5 to the matrix
* QA: Removing PHP8.5 due to dependency issues
* QA: Add the DB version to the testing output
* QA: Switch back to MySQL for the moment
* QA: More fidelity in reporting
* QA: The pipe must be mixed
* QA: Moving audit_schema.php changes from 1.2.x
* QA: Moving audit_schema.php changes from 1.2.x
* QA: Restore mysql monitoring
* QA: php-cs-fixer issues
* QA: Attempt to roll back to MariaDB 10.6
* QA: Attempt to fix check_all_pages.sh
* QA: Make installer functional again
* QA: Fix installer php-cs-fixer issues
* QA: Type to a string
* QA: Get the database version correctly
* QA: Fix issue with reports in check_all_pages.sh
* QA: Check the server version in the right place
* Feature: Support SHA256 as a new hash for passwords
* QA: Function definition and return typing audit
* QA: Refinement of form types
* QA: Refinement of form types
* QA: Consistency of comments
* QA: Issues with php-cs-fixer and more comments
* QA: More typing issues
* QA: php-cs-fixer on merge conflict resolution
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This removes most entries to $config in the base code. A few new constants were defined to achieve this:
* CACTI_CONNECTION - The status of the current connection
* CACTI_CSRF_SECRET - The path to the csrf secret file
* CACTI_PHP_SNMP - True if php-snmp is installed
* CACTI_WHITELIST - The path to the Cacti Whitelist file if defined
I also moved several $config['poller_id'] to the existing POLLER_ID and move a number of $config['is_web'] to the existing CACTI_WEB constants.
There remain a few artifacts in the code. They will be handled in a separate commit.
* Introduce a new wrapper function for showing the show/hide column indicator
* Migrate all Core packages to use that new wrapper function
* Migrate pages to have JavaScript show immediately below the form object.
* Correct some indentation issues
* #5140: Cacti PHP 8.2 SNMP Errors with php-snmp Installed
* #5142: Correct issues with permission model including display of authorization UI elements and warnings
* #5143: When a Device has zero Graphs or Data Sources, it does not display the correct value
- When a developer uses backtracing, HTML output can be seen from command line bug confirmed
- When using `input_validate_xxx`, calls to `die_html_input_error()` do not pass variable name bug confirmed
Closes#3559Closes#3560
Update loadPage calls to be loadUrl
Update loadPageNoHeader calls to be loadUrl calls
Also includes changes to make logout adhere to new html_auth_xxx functions
* feature#4948 - properly redirect when SSO session expires
* allow layout.js detect errors and redirect, in the case of a session timeout for example
* remove some inline javascript and move to ready function
* debounce some pages that were redirecting due to change in layout.js
* old page bindings on new page loads
* ensure use of undefined and typeof 'undefined' are properly used
* switch use of strURL to href in layout.js
- This change moves the function get_permission_string() to lib/auth.php
- Additionally, it makes the "Details" display on the Graph permissions consistent with the User Administration page.
- User and Group Administration - Unused Templates are missing and row count wrong on Group page
- Some light cleanup of filter checks
- Add some prepared statements