mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-27 07:13:15 +09:00
develop
183
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
41e6d9e033 |
security: consolidate verified GHSA fixes for develop (batch 4) (#8145)
* 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 |
||
|
|
3ab4c69fb7 |
PHPStan Level 8 - Phase 1 Conversion (#8135)
* PHPStan Level 8 - Phase 1 Conversion
Reduces the real (no-baseline) PHPStan level 8 error count from ~2,724 to 425
and regenerates phpstan-baseline.neon accordingly (8,941 -> 1,921 lines).
Core type-safety changes
- lib/database.php: narrow db_fetch_row()/db_fetch_row_prepared() to return
array (was bool|array) and db_fetch_assoc()/db_fetch_assoc_prepared() to
return array (was mixed); the _prepared workers coerce the connection-failure
path to an empty array so the declared type is honest. empty()/cacti_sizeof()
checks are unaffected.
- lib/database.php: narrow $db_conn guards from is_object() to instanceof PDO in
the transaction/quote/insert-id helpers so the PDO calls resolve.
- lib/mib_cache.php: the fluent MibCache methods mib()/object()/table()/row()
now return self instead of a bare object so chained calls type-check.
Type-safety casts and guards (mechanical, behaviour-preserving)
- Cast string|false/|null builtin results feeding string parameters
(json_decode, base64_encode, trim, htmle, preg_replace, explode, etc.).
- Cast int|string / int|false values feeding int id/pid parameters.
- Guard resource|false fopen()/popen() handles before fwrite/fclose/fread, and
wrap foreach over array|false/list|false results with `?: []`.
Genuine bugs found and fixed
- cli/add_tree.php / lib/api_tree.php: site tree nodes could not be created via
the CLI - the --site-id option was never parsed, $nodeTypes had no 'site'
entry (passing null to api_tree_item_save(int $type) -> TypeError), and
api_tree_item_save() never persisted site_id. All three fixed.
- tree.php: leaves_exist() is typed : int but returned db_fetch_assoc_prepared()
(an array of rows) for a SELECT COUNT(*); now uses db_fetch_cell_prepared()
and returns the scalar count.
- lib/mib_cache.php: $entries_per_object was a float (division / ceil) used as
an array key (PHP 8.1 implicit float-to-int key deprecation); now cast to int.
Config
- .phpstan.neon: add notIdentical.alwaysTrue and booleanAnd.alwaysFalse to the
existing always-true/false ignore family (same "PHPStan gets confused"
dynamic-constant cause already covered by identical.alwaysTrue,
notEqual.alwaysTrue, booleanAnd.leftAlwaysTrue, etc.).
- phpstan-baseline.neon: regenerated; the remaining 425 entries are the
untouched long tail for Phase 2.
* Remove redundant @phpstan-ignore comments
Follow-up cleanup for the level 8 Phase 1 work. Removes 14 inline
@phpstan-ignore comments that no longer suppress any reported error:
- cli/repair_database.php: `@phpstan-ignore booleanAnd.alwaysFalse` is now
covered by the global booleanAnd.alwaysFalse ignore added to .phpstan.neon.
- 13 others (host.php, include/global.php, include/session.php,
lib/api_automation.php x2, lib/functions.php x2, lib/html_utility.php x2,
lib/installer.php, lib/package.php, lib/reports.php, lib/rrd.php) no longer
match any reported error after the type-safety fixes (e.g. the
db_fetch_row_prepared() return-type narrowing removed the offset-assign
errors the api_automation ignores were suppressing).
Verified with reportUnmatchedIgnoredErrors enabled: 0 unmatched ignores
remain and the full level 8 run still reports 0 errors.
* ci: satisfy validator ratchet and refresh security sink baselines
- lib/api_tree.php: give the new tree-item site_id a real numeric
constraint ('^[-0-9]+$', matching html_reports.php) instead of an
empty regex, so the validator constraint ratchet passes without
bumping its baseline.
- tests/security/baselines: refresh the three sink/hotspot signatures
whose code text changed from the (string) casts added in this branch
(lib/poller.php setsid, cli/rrdresize.php json_encode, lib/import.php
simplexml_load_string).
* ci(js): allow DOMPurify 3.4.16 and update sync_js pin test
The dependabot bump (#8134) moved package.json/package-lock.json to
DOMPurify 3.4.16 on develop but left tests/js/sync_js.test.mjs pinned to
3.4.15, so the PR merge commit fails the 'DOMPurify is pinned' contract.
Bring package.json/package-lock.json to 3.4.16 (matching develop) and
update the pin test to expect 3.4.16.
* test: update sql.php null-handling assertion for the (string) cast
This branch changed scripts/sql.php from trim(\ ?? '') to
trim((string) \) (the phpstan-safe form that coerces both null and
false from shell_exec()). Update SqlScriptsTest's null-return assertion
to match the new cast instead of the removed '?? ''.
* fix: address Copilot review - ownership IDs, fopen guards, mib_cache bound
- chown()/chgrp(): pass integer UID/GID from fileowner()/filegroup()
(guarding the false lookup) instead of string-casting them, which made
them resolve account/group names like '1001' and fail. Covers
lib/api_device.php, lib/boost.php and poller_maintenance.php (x2).
- fopen() failure now short-circuits instead of reporting success:
lib/package.php returns false, lib/clog_webapi.php and utilities.php
render an error, and snmpagent_mibcachechild.php skips the cache write
and sentinel unlink so a concurrent writer's lock is preserved.
- lib/mib_cache.php: keep the float quotient as the loop bound and cast
only the array offset, so a non-even entries/columns split no longer
truncates the loop and drops a cached row.
* revert: keep db_fetch_* returning false on error; baseline Level 8 instead
Per review, restoring the intentional fail-safe: db_fetch_row[_prepared]()
return bool|array and db_fetch_assoc[_prepared]() return mixed again, so a
genuine SQL error (not just a missing connection) is signalled as false and
the === false checks in cdef_is_in_use(), boost_process_* and aggregate.php
work as before. Dropped the is_array() ? : [] coercion.
Level 8 stays green by regenerating phpstan-baseline.neon to capture the
re-introduced bool|array/mixed call-site errors (the ~1,850 the narrowing
had eliminated). Tightening those callers to drop them from the baseline is
Phase 2 work.
---------
Co-authored-by: TheWitness <copilot@users.noreply.github.com>
|
||
|
|
f956ea5a5c |
Convert generic <select> elements to select2(), with new class helpers (#8053)
* feat: convert generic <select> elements to select2, with new class helpers
Replaces the jQuery UI selectmenu() catch-all in setSelectMenus() with select2,
applied uniformly to single and multi selects. Fewer than 10 options disables
the search box (minimumResultsForSearch: Infinity); 10 or more enables it -
same threshold now applied to the existing select2/select2-multi classes.
New layout.js class helper: select2-multi-count, a multi-select whose
selection summary reads "N Selected"/"All Selected" instead of one chip per
option (generic multiSelectAllText/multiSelectCountText strings in html.php,
overridable per-field via data-select-all-text/data-select-count-text/
data-select-all-value). graph_template_id (html_graph.php x2, html_tree.php)
now uses it in place of the jquery.multiselect-based .graph-multiselect,
preserving the existing "All Graph Templates"/"N Templates Selected" wording
and the -1 "all" sentinel behavior (reimplemented via select2:select/unselect
events in setSelectMenus()). The old .graph-multiselect jquery.multiselect
init block is left in place (now unreachable for core's own markup) in case
a plugin/theme still emits that class itself.
select2-callback is reworked from its previously-unused static-URL contract
into an ajax-backed replacement for the legacy .drop-callback/makeCallbacks()
autocomplete widget: data-action + data-variables build the query the same
way makeCallbacks() already did (pageName + action + live values of other
named fields + search term), and data-callback still names a JS function to
invoke on selection, matching form_callback()'s existing $on_change/$class
contract. form_callback() only renders the new <select> markup when its
$class parameter contains select2-callback (opt-in); every existing caller
that doesn't request it keeps the exact legacy output. html_graph.php's
host_id filter (both places) opts in. form_multi_dropdown() gained optional
$select_all_text/$select_count_text/$select_all_value parameters (all
additive/backward compatible) to plumb the graph_template_id wording through.
Compatibility: an org-wide code search found no plugin depending on the
.select2-callback/.graph-multiselect/.drop-callback/makeCallbacks() internals
being changed here (form_callback()'s default output is unchanged; the
.graph-multiselect jquery.multiselect init stays available). Everywhere else
in core that assumed the old jQuery UI selectmenu widget on elements now
covered by the broadened catch-all (disableField()/enableField(), the SNMP
security-level/protocol refresh logic, realtime.js's ds_step/graph_start/size
refresh, api_aggregate.php's field enable/disable, and html_reports.php's
branch_id/site_id/host_template_id handling) now branches on
.select2-hidden-accessible and uses select2's own refresh mechanism
(.trigger('change.select2')) instead, alongside the untouched legacy
selectmenu branch. #user_language and #i18n_default_language (which get
their own bespoke flag-icon languageselect widget) are excluded from the
catch-all, same as before.
The install wizard (install/install.js) has its own independent selectmenu
initialization and is intentionally left untouched.
* fix: use json_encode for select2 multi-select JS translation strings
* fix: make select2 initializers idempotent to stop duplicate widgets
applySkin() (which calls setSelectMenus(), where every select2/select2-multi/
select2-multi-count/select2-callback/catch-all initializer lives) runs more
than once per page view - once from cactiReady() on initial load, and again
from the generic AJAX-completion handler after any loadUrl()/postUrl() call,
which most list/filter pages already trigger during their own initial load.
Since calling .select2() a second time on an element that already has it
initialized creates a second, independent .select2-container next to the
first (select2 does not no-op or tear down the previous instance), every
affected <select> ended up rendering twice. Guard every initializer (plus
the graph_template_id -1 sentinel's event bindings, now namespaced and
unbound first) so a second setSelectMenus() pass skips elements already
marked .select2-hidden-accessible.
* fix: match select2 dropdown styling to the dark theme's real button look
border-radius was 4px (should be 6px, matching .ui-corner-all used
everywhere else); the selection box and dropdown panel were flat black
instead of this theme's actual .ui-button/.ui-widget-content backgrounds
(a subtle gradient-highlight image and a repeating texture image,
respectively). Also add a min-width and force the selected text/dropdown
option list to a single line instead of wrapping.
* fix: match select2 dropdown styling to each theme's real button look
Same fix as the earlier dark theme commit, applied to the remaining themes.
Every theme's select2 override previously used generic placeholder colors
(border-radius: 4px, background: #ffffff/#222222) that did not match that
theme's actual .ui-state-default/.ui-button/.ui-widget-content styling:
- cacti, carrot, hollyberry, raspberry, modern, paw: selection box now uses
the real button gradient-image background instead of flat white; dropdown
panel background already matched and is unchanged.
- sunrise: selection box background corrected to transparent (matching its
real button style) and the dropdown panel to its real black background,
instead of flat white for both.
- paper-plane: selection box background corrected to this theme's real
near-black button color instead of flat white.
- midwinter: switched from hardcoded generic colors to this theme's own
CSS custom properties (var(--border-color), var(--background-content),
var(--text-color-lighter), etc.), matching jquery-ui.midwinter.css.
border-radius is now 6px everywhere, matching .ui-corner-all. All themes
also gained a min-width and forced the selected text/dropdown option list
onto a single line instead of wrapping.
* fix: default select2's dropdownAutoWidth to true
The legacy jQuery UI selectmenu widget always sized its open dropdown to fit
the widest option, regardless of how narrow the closed control itself was.
Select2 defaults to matching the dropdown's width to the control's, so wide
option text was wrapping/truncating inside a narrow panel. Set this as a
global default once instead of touching every individual select2() call.
fix: destroy any existing select2 widget before re-initializing
applySkin() runs more than once per page view. The existing
:not(.select2-hidden-accessible) guards were meant to make re-running the
select2 initializers a no-op, but duplicate widgets were still being
reported. Explicitly tear down any select2 instance still attached right
before the initializers run again, so a widget can never end up duplicated
regardless of why applySkin() re-ran.
fix: don't select2-ify a select a plugin already widget-ified with selectmenu
Symmetric to the above: if a plugin's own script already deliberately
applied jQuery UI selectmenu to one of its selects (a few do, for their own
dynamically-created fields), skip converting it to select2 too.
* fix: convert the Device filter's legacy drop-callback widget to select2-callback
html_host_filter()'s autocomplete-enabled branch never got the select2
treatment applied to every other filter field - it still built its own
<input class='drop-callback'> wired up by the older makeCallbacks()/jQuery UI
autocomplete widget (styled with the legacy ui-selectmenu-button markup),
instead of opting into form_callback()'s newer select2-callback rendering like
everything else. Left side-by-side with now-modernized neighboring filters,
this old widget stood out as a leftover "old select". Switch it to the same
select2-callback select markup (data-action='ajax_hosts',
data-variables='site_id') the 1.2.x branch already uses, reusing the existing
ajax_hosts handlers and get_allowed_ajax_hosts()'s id/label response shape.
* fix: restore select2's gradient after closing without selecting, shrink its height, and drop the now-unneeded min-width
Every theme's active/open select2 style also matched .select2-container--focus,
but select2 leaves that class on the container after the dropdown closes (it
only drops --open), so the flat "active" background stuck around until the
next selection instead of the gradient returning right away. Scope the active
look to --open only.
Also shrink the single-select control from select2's stock 28px down to 24px
(and its arrow/rendered text to match) so it sits closer to the jQuery UI
button height it's replacing, and drop the min-width: 160px placeholder added
earlier to keep wide option text from being clipped - dropdownAutoWidth now
sizes the open dropdown to its content regardless of the closed control's
width, so the constraint is no longer needed.
* feat: add configurable select2 search threshold; drop autocomplete_enabled on develop
Add the same Select Search Minimum Rows setting added on 1.2.x, wiring it
through as the select2SearchRows JS global (include/global_session.php) and
replacing the hardcoded 10-option cutoff in every select2 initializer in
layout.js.
Remove Autocomplete Enabled entirely on develop: it only ever existed to let
the Classic theme opt out of the ajax-backed callback widgets, and Classic
doesn't exist as a develop theme. html_host_filter() and the Graph Items data
source field now always use the ajax-backed rendering (select2-callback /
drop_callback) unconditionally instead of branching on the removed setting.
* fix: keep the first 20 select2 results visible before scrolling
Select2's stock results list only guaranteed ~7-8 rows (200px) before
scrolling. Pin each result row to a consistent 24px (matching the shrunk
control height) and size the list's max-height to fit 20 of them before the
scrollbar kicks in.
* fix: repair layout.js corruption from the select2SearchRows commit, and exclude .multiselect from the catch-all
A faulty automated edit in
|
||
|
|
1e5329dd89 |
security: consolidate verified GHSA-rjvj win32 cmd.exe hardening for develop (#8056)
* fix(win32): harden the cmd.exe shell sinks on develop (GHSA-rjvj-r52f-8v5q) Forward-port of the 1.2.x win32 command-injection remediation. On Windows the SNMP/ping/data-query/trap commands run through cmd.exe, which ignores the \" escape and toggles quoting on every ", so cacti_escapeshellarg cannot stop & | ^ < > ( ). - add cacti_escapeshellarg_cmd(), stripping those operators on win32 before quoting (a Unix pass-through) - snmp_escape_string(): strip the operators in the win32 branch - route the SNMP binary hostname, the data-query device values (get_script_query_path), the data-input arg builders, the Windows ping hostname, and the SNMP trap notification arguments through the strip get_script_query_path is device-reachable (a rogue monitored device supplies an SNMP index/system field that executes on the Windows poller); the rest are post-auth. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(win32): strip %VAR% from the hostname on Windows (GHSA-rjvj-r52f-8v5q) cmd.exe expands %VAR% even inside quotes, so a device hostname of %USERNAME% would expand into the SNMP/ping command line. Add an opt-in $strip_env flag to cacti_escapeshellarg_cmd() and set it for the SNMP binary and ping hostnames, which never legitimately contain a percent. Community and credential values are left untouched because they can legitimately contain %. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs(changelog): note win32 cmd.exe hardening for develop * security: require Package Management permission to trust new package signers package_accept_key() (reachable via the repository-based package import flow) inserted new keys into package_public_keys, the global trust store consulted by import_validate_signature() for every future import by every user, without checking for the Package Management (realm 29) permission that gates package_keys.php/package.php/package_repos.php for the same table. An Import Templates (realm 17) user could therefore add themselves as a trusted signer for the whole install. Also add the 'accept' action to the CSRF-protected bad_actions list so the acceptance step requires POST plus a valid token like every other state-changing action. GHSA-gxgm-8rhv-r7jv * docs(changelog): note package-signer trust authorization fix * security: close tab-based open redirect bypass in CSRF timeout handler sanitize_uri()'s guard ( |
||
|
|
a2c8df612e |
fix(csrf): require POST tokens for state-changing actions (#7991)
* fix(csrf): require POST tokens for item actions * test(csrf): cover every guarded action path * test(csrf): keep legacy guard contract extensible * fix(csrf): hide POST-only targets from crawlers * test(csrf): reject every crawlable state-action link * fix(csrf): fail closed without logging crawler probes * fix(csrf): post data-query item actions safely Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(csrf): normalize stripped token separators Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(csrf): distinguish method and token failures Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(csrf): escape POST action URL attributes Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(csrf): delegate POST action events Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(csrf): post data template add action Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * style(html): align POST button class Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
e8ec3ca0ec |
ci: consolidate pest coverage gate re-enable and validator constraint ratchet (#7516)
* ci: consolidate coverage and validator quality gates * fix(audit): handle opening and multiline comments * style(tests): align shared Orb assertions * test(orb): require the configured runtime machine * revert(tests): leave macOS Orb integration out of scope * fix: Fix ci update * fix: Remove imagedestroy calls from merge conflict --------- Co-authored-by: TheWitness <thewitness@cacti.net> |
||
|
|
656c5e66b2 |
security(reports): cast report id before the edit redirect (#7304)
* security: cast report id to int in save redirect Location header Psalm taint analysis flagged $post['id'] flowing unescaped into the edit redirect. PHP blocks CRLF and the host is fixed, so this is defense-in-depth. Route the redirect through reports_redirect_url(), which casts the id to int and strips any query/parameter injection. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test reports redirect cast with regex --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> Co-authored-by: TheWitness <thewitness@cacti.net> |
||
|
|
b2bf39b8dc |
fix(sqli): sanitize sort_column and enforce sort_direction in ORDER BY clauses (#7162)
* fix: correct grammar and possessive errors in English source strings (batch 2) (#1) * fix: correct grammar and possessive errors in English source strings (batch 2) Seven errors found via cacti.pot audit: - automation_networks.php: "senders name" → "sender\'s name" (line 839) - automation_networks.php: "senders Email" → "sender\'s Email" (line 848) - automation_templates.php: "devices sysDescr" → "device\'s sysDescr" (line 1060) - automation_templates.php: "devices sysName" → "device\'s sysName" (line 1067) - automation_templates.php: "devices sysOid" → "device\'s sysOid" (line 1074) - data_templates.php: garbled "it either it value...critical data Data Query" → "its value...Data Query" (line 903) - package_repos.php: "Package Repositorites" → "Package Repositories" (line 436) All changes are to UI description strings inside __() / __esc() calls. cacti.pot should be regenerated via build_gettext.sh after merge. * fix: correct grammar and possessive errors in English source strings (batch 2) Seven errors found via cacti.pot audit: - automation_networks.php: "senders name" → "sender\'s name" (line 839) - automation_networks.php: "senders Email" → "sender\'s Email" (line 848) - automation_templates.php: "devices sysDescr" → "device\'s sysDescr" (line 1060) - automation_templates.php: "devices sysName" → "device\'s sysName" (line 1067) - automation_templates.php: "devices sysOid" → "device\'s sysOid" (line 1074) - data_templates.php: garbled string → "its value...Data Query" (line 903) - package_repos.php: "Package Repositorites" → "Package Repositories" (line 436) All changes are to UI description strings inside __() / __esc() calls. cacti.pot should be regenerated via build_gettext.sh after merge. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: add dependabot config with npm and github-actions * ci: add CodeQL (JS/TS, excludes PHP) with workflow_dispatch * ci: update CodeQL for javascript-typescript, python * fix(ci): use specific runner labels, fix codeql concurrency * Improve IPv6 support in RRDtool proxy and ping utilities (#2) * Improve IPv6 support in RRDtool proxy and ping utilities - Fix RRDtool proxy to dynamically detect IPv6 addresses and use AF_INET6 sockets instead of hardcoded AF_INET (IPv4-only), enabling connections to IPv6 RRDtool proxy servers including backup servers - Strip brackets from IPv6 addresses before passing to socket_connect - Properly close failed sockets before creating new ones for failover - Replace fragile str_contains(':') IPv6 detection in ping with filter_var(FILTER_FLAG_IPV6) for more robust address validation https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Fix JS code quality: implicit globals, deprecated APIs, loose equality - Add var declarations to prevent implicit globals in install.js (element, enabled, button, buttonCheck) - Remove console.log debug output left in production (install.js) - Replace deprecated jQuery .unbind() with .off() (layout.js) - Fix "depreciated" typo to "deprecated" in deprecation warnings - Convert == / != to === / !== for null, boolean, string, typeof, and numeric comparisons across install.js and realtime.js https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Replace deprecated jQuery shorthand event methods in layout.js Replace .click(), .keyup(), .keydown(), .mousedown(), .mouseenter(), .mouseleave(), .submit(), .resize() with .on() equivalents. Replace .focus(), .change() trigger calls with .trigger(). These shorthands were deprecated in jQuery 3.5. https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Replace deprecated jQuery methods in realtime.js Replace .bind() with .on() and .change() trigger calls with .trigger('change'). .bind() was deprecated in jQuery 3.0 and shorthand triggers in jQuery 3.5. https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Replace deprecated jQuery methods in install.js and fix ===/!== errors Replace .click(), .change(), .focus() with .on()/.trigger() equivalents. Also fix !=== and ==== operators that were incorrectly introduced by a prior replace-all of == to === within existing !== and === expressions. https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Restore == null where needed to catch both null and undefined In JavaScript, == null matches both null and undefined, which is an intentional idiom. The prior === null conversion broke cases where values come from jQuery .val(), .data(), $.urlParam(), or object property access that may return undefined rather than null. Revert those specific cases while keeping === null where variables are explicitly initialized to null. https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Replace deprecated jQuery methods in all theme main.js files Replace .unbind().click() with .off('click').on('click'), convert .hover() to .on('mouseenter').on('mouseleave'), replace .change(), .scroll(), .click() shorthands with .on() equivalents, and .blur() with .trigger('blur') across all 10 theme files. https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Convert string concatenation to template literals Replace 'str' + var + 'str' patterns with ES6 template literals in realtime.js and install.js. Improves readability especially for URL construction and HTML building. Also replace $.parseJSON() with native JSON.parse() in realtime.js. https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo * Convert var to const for single-assignment variables Replace var with const where the variable is assigned once and never reassigned within its scope, in install.js and realtime.js. Keeps var for variables that are conditionally reassigned (e.g. size, url). https://claude.ai/code/session_01SbuDigvAkYvPKvdcougsdo --------- Co-authored-by: Claude <noreply@anthropic.com> * fix(sqli): sanitize sort_column and enforce sort_direction in ORDER BY clauses Closes GHSA-q9xg-p762-9jm3 and GHSA-72vr-jr4v-55vf. - Add sanitize_sql_column() to lib/functions.php stripping all chars outside [a-zA-Z0-9_().] from user-supplied column names - Apply sanitize_sql_column() at every ORDER BY concatenation in api_automation.php and html_reports.php - Enforce direction to literal ASC/DESC in html_reports.php, api_automation.php, and html_utility.php (update_order_string, get_order_string) - Add tests/Unit/SafeSortTest.php with 22 stub-based regression tests Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(docs): move sanitize_sql_column above sanitize_search_string docblock The sanitize_search_string docblock was orphaned after sanitize_sql_column was inserted between it and the function body. Reorder so each function follows its own docblock directly. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(sqli): escape apostrophes in automation_templates and harden sort_direction in display_matching_hosts Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(sqli): restore allowlist guard, sanitize session keys, add sanitize_sql_column default Restore the preg_match allowlist guard in get_order_string() that was removed by the PR, re-opening the ORDER BY injection surface. When the request var is empty after sanitization, return '' rather than building a malformed ORDER BY clause. Sanitize sort_column before storing as SESSION array key in update_order_string() and add read-time guard in the inplace loop that rebuilds ORDER BY from stored keys. Add $default parameter to sanitize_sql_column() so callers get a safe fallback instead of an empty string that produces 'ORDER BY ASC'. Fix inconsistent INET_ATON substitution in display_matching_hosts(). Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * Improve sanitize_sql_column function Fix regex to sanitize SQL column names properly. * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: TheWitness <thewitness@cacti.net> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
122bb88387 |
chore(security): harden report actions and theme handling (#7169)
* fix(security): align develop with advisory hardening Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(security): harden remote agent auth compatibility Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(security): reorder remote auth checks Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(security): harden remote_agent auth order and query scope Move whitelist check before the single-poller guard so single-poller installs relying on the whitelist are not incorrectly rejected. Narrow SELECT * to SELECT hostname; the loop only reads hostname. Drop function_exists guards around md5/hash; both are PHP core and the raw $cache_seed fallback is unsafe as an APCu key. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(theme): cast read_config_option result to string in cacti_validate_theme read_config_option can return false or null when the setting is absent. Without the cast, a strict comparison to '' would not match, leaving $default unset and risking a null-typed value flowing into callers. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(reports): skip invalid IDs in bulk action without aborting the loop Replace input_validate_input_number (which calls die_html_input_error on bad input, aborting the entire bulk action) with an inline guard. Cast $report_id to int at call sites where the signature requires int. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * feat(security): comprehensive UI hardening and 7.4 normalization - Refactored poller_spikekill.php to use array-based execution and sanitized SQL IN clauses. - Refactored script_server.php Windows process check to use cacti_exec. - Hardened snmpagent background process lifecycles. - Standardized version checks in support.php and utilities.php. - Replaced short array syntax [] with array() and verified 7.4 compatibility. - Synchronized all hardened files to primary developer path. * fix(snmpagent): replace undefined cacti_process_execute() with exec_background() cacti_process_execute() was called but never defined, causing a PHP fatal. Replaced with exec_background() from lib/poller.php. Also fix pre-existing parse error in snmpagent_persist.php ([ closed with ) instead of ]). Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * style: convert new code to short array syntax php-cs-fixer (array_syntax/list_syntax short) flagged array() introduced on this branch; convert to [] so the coding-standards gate passes. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * revert off-topic exec changes to match develop poller_spikekill, script_server, snmpagent_persist/mibcache and support had been switched to 1.2.x-style cacti_exec(), which is undefined on develop and failed phpstan. Restore develop's native exec() idiom; these files are outside this PR's scope (report actions and theme handling). Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * build: pin phpstan to 2.2.1 phpstan 2.2.2 added a stricter is_numeric() always-true inference that fails on pre-existing develop code (lib/data_query.php); pin until that is addressed upstream so CI is reproducible. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(reports): deserialize type-prefixed bulk items so actions run Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: ignore phpstan function.alreadyNarrowedType identifier Clears the level 6 alreadyNarrowedType error on lib/data_query.php:2591 that develop currently emits, matching the sibling narrowing identifiers already ignored. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix: add missing PCRE delimiters to graph_template_id regexp filter Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(reports): parse the confirm list identically to the action branch Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * refactor(remote_agent): drop the APCu auth cache (uncertain dependency, cross-request only) Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * Enhance security checks for remote agent access --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> Co-authored-by: TheWitness <thewitness@cacti.net> |
||
|
|
c376d2eabc |
fix(security): parameterize untrusted SQL inputs across develop (#7210)
* fix(security): parameterize untrusted SQL inputs across develop Bind, db_qstr, or integer-cast request-derived values that previously reached SQL by interpolation: RLIKE/REGEXP filters in graph/tree/report views, IN() id lists in device, profile, and SNMP receiver management, host_template_id in automation matching, and ORDER BY columns in the automation match pages (allowlist + ASC/DESC). Validate graph_name_regexp at save and anchor the graph_template_id filter regex. Covers CVE-2026-46531. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * style: apply php-cs-fixer single-quote and alignment fixes Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: ignore phpstan function.alreadyNarrowedType identifier Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
27919c50d7 | Updating Copyrights to 2026 (#6578) | ||
|
|
b993471579 |
Fix #6539 - Allow Standard Cacti Log Files to be Rotated on Demand,PHPdoc, and Typing (#6540)
* 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> |
||
|
|
1627c7a150 | Font Awesome Icons to Tabler Icons migration | ||
|
|
b9334a15d9 | QA: Updates for files for php-cs-fixer and some php-doc changes | ||
|
|
b28563766b |
add missing + button (#6242)
* add missing + button * add any default value |
||
|
|
685d4b9357 | Start addressing PHPStan Issues | ||
|
|
e5c4015e0e |
QA: Remove most references to $config
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. |
||
|
|
2c779273f9 | Copyright Updates and PHP-CS-Fixer updates | ||
|
|
ea5429c03a | Fixing some invalid lint updates | ||
|
|
d68942c84f | QA: Remove name space collisions causing vscode issues | ||
|
|
ad071ac391 | QA: Fix: #6169 - Device filter looses state | ||
|
|
65ab16f5cf |
Start converting to newer PHP Syntax and Functions (#6103)
* Add Rector * Add Rector * Fix "Cashed" misspelling Also harmonize the phrase with the one below it * Fix implode error in db_table_create Only relevant when multiple primary keys * Fix auth issue, parentheses in the wrong location Was causing too many arguments to be sent to cacti_sizeof which only take 1, instead of get_allowed_devices. * Fix issue with session_var not properly using class variable * Fix pass by reference error in get_allowed_devices get_allowed_devices has a pass by reference on the "total_rows" field. It is used in several places to pass the total_rows back to a counter. Here though, we are passing a number directly to the function, which errors out with "Uncaught Error: get_allowed_devices(): Argument #4 ($total_rows) cannot be passed by reference". So we will just place a dummy variable in front to catch the pass. This wasn't caught before because the previous parentheses issue. * Fix undefined variable "field_array" in html_filter * Fix undefined function 'get_nfilter_filter_request_var' * Fix undefined variable 'resizable' I corrected the function parameter, as that was technically the incorrect spelling * Fix invalid variable $user_id * Fix undefined vars in spikekill class * Fix copy and paste error Oops * Forgot to use the dummy variables * Add missing $ Oops * Start converting to newer PHP Syntax and Functions * Test fixing the workflow by install composer * Lets not valid the composer file right now Seems we have a few things to fix it in * Validate composer * Lite formating changes * lite formatting * lite formatting * lite format changes * lite format changes * lite format changes * lite format changes * lite format changes * lite format changes * lite format changes * lite format changes --------- Co-authored-by: TheWitness <thewitness@cacti.net> |
||
|
|
d88d3acd30 | reverting FontAwesome till better solution has been identified. | ||
|
|
22180140a7 | QA: Fix: #6056 - Missing Table when editing Report | ||
|
|
5be7d7f18b | Migrating icons from FontAwesome to Tabler | ||
|
|
4a01ef7f05 | QA: Tweak a few Reports visual settings | ||
|
|
b98323c966 |
feature: Remove old Lotus Notes Attachment Types from Reports
* There is no longer a reason to have Lotus Notes Attachment Types |
||
|
|
408b95d09a |
Fix: 6044 - Add the ability to view old reports
* Enable the capabilities to view historical Classical Cacti Report from the GUI * Also added ability to view Run Limit in this commit |
||
|
|
5056c3ed0c | QA: Call with queue id of 0 for realtime report runs | ||
|
|
911e3ed3a3 |
QA: Adding more iconography
* Conserves space and provides more detail. |
||
|
|
849692f145 | QA: Change positioning and iconography | ||
|
|
de16bf1b73 | QA: Add ReportIt to Supported Report Actions | ||
|
|
9619488f91 | QA: Notify list not saving | ||
|
|
a791a0845f |
feature: Allow Reports to be send to a Notification List
* This requires thold to first be installed. |
||
|
|
471ba25837 | QA: Correcting typo | ||
|
|
8bfbc7221d | QA: Minor tweaks | ||
|
|
5506e2166c | QA: Log the source and better language | ||
|
|
5925f3ceb9 |
QA: Enable ReportIt from the Report Interface
* Still have to convert ReportIt editing into an API so that it can be called from within reports. |
||
|
|
589a5e2a12 |
QA: Move $save operation to api_scheduler.php
* This allows us to keep control of behavior consistently during save operations across consumers of the API. * This will soon be incorporated into ReportIt |
||
|
|
1326f6b594 | QA: Reports scheduling is working again | ||
|
|
f959625453 |
QA: Fixing Classic Reports Page
* Convert to Filter Table * Update Row Display Data * Start to weave in ReportIt Reports * Before we can enable the ReportIt Reports, I still need to make changes to ReportIt 3.0 |
||
|
|
57500ad150 |
QA: First attempt to move Reports to Scheduler
* This interface has not been tested yet. Should be running by the end of the week. |
||
|
|
dee98cf953 | QA: Two missing commits | ||
|
|
24d988cc66 |
QA: #5858 - Reporting Changes
* As part of the reporting project remove reports_user.php and rename reports_admin.php to simply reports.php. * Control permissions by realm and not file in this case. |
||
|
|
ad07471bb1 |
Lots of PHPDoc formatting and cleanup
Lots more to go |
||
|
|
581d6d8d75 | QA: Use a unique session variable | ||
|
|
5c9d468671 | - add data-DefaultLabel tag to all filter related select fields. | ||
|
|
541cebc48e |
Fixing #5792: Fixing Reporting from List View
* Unable to add Graphs to a Report from Cacti List View * QA: Show date correctly on schedule |
||
|
|
1aa72d24c9 | QA: Update Copyright to 2024 | ||
|
|
a4d1e6fd1c |
QA: Add Reports to Confirmation API
* Adding Reports to Confirmation API * Fix HtmlSanitize vs. DOMPurify * Re-organize the Reports Actions |