hardening: prepared statements, PHP 7.4 idioms, and security fixes#215
hardening: prepared statements, PHP 7.4 idioms, and security fixes#215somethingwithproof wants to merge 6 commits into
Conversation
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to harden the plugin by modernizing PHP idioms and reducing command/filename injection risk in a few execution and sanitization paths.
Changes:
- Refactors several
isset()/ternary patterns to??and??=for clearer defaults. - Adds extra config filename sanitization to reject Windows path separators (
\). - Hardens external command construction for
rrdtoolandfpingviaescapeshellarg()and additional input validation.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/WeatherMap.functions.php | Uses ??= to default $decimal when unset. |
| lib/WeatherMap.class.php | Replaces isset(...)?...:'' patterns with ?? for backtrace/tag defaults. |
| lib/editor.inc.php | Adds Windows path separator rejection in .conf filename sanitizer. |
| lib/datasources/WeatherMapDataSource_rrd.php | Escapes rrdtool args with escapeshellarg() when building shell command strings. |
| lib/datasources/WeatherMapDataSource_fping.php | Adds target validation and escapes the target before executing fping. |
| cli/cacti-mapper.php | Simplifies nested nicename selection using ??. |
Comments suppressed due to low confidence (2)
lib/datasources/WeatherMapDataSource_rrd.php:318
- $extra_options (from the
rrd_optionshint) is appended to the shell command without any escaping/validation. That leaves a shell-injection path even though the main args are now escaped with escapeshellarg(). Consider parsing$extra_optionsinto discrete args and escaping each, or restricting it to a validated allow-list of supported rrdtool flags.
$command .= ' ' . escapeshellarg($arg);
}
$command .= ' ' . $extra_options;
lib/datasources/WeatherMapDataSource_rrd.php:418
- $extra_options is appended to the constructed rrdtool shell command without escaping/validation. This preserves a shell-injection path even after escaping the primary args. Consider splitting
$extra_optionsinto args and escaping each, or limiting it to an allow-list of safe flags.
$command .= ' ' . escapeshellarg($arg);
}
$command .= ' ' . $extra_options;
| wm_warn("FPing ReadData: rejected target with illegal characters ($target) [WMFPING04]"); | ||
|
|
There was a problem hiding this comment.
The rejection warning logs the raw $target value. Because this branch is reached specifically for “illegal characters”, an attacker could include newlines/control characters and cause log injection/formatting issues. Consider sanitizing the value before logging (e.g., replace non-printables or log an encoded representation) while still preserving troubleshooting value.
| wm_warn("FPing ReadData: rejected target with illegal characters ($target) [WMFPING04]"); | |
| $log_target = json_encode($target, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); | |
| if ($log_target === false) { | |
| $log_target = '"[unencodable target]"'; | |
| } | |
| wm_warn("FPing ReadData: rejected target with illegal characters ($log_target) [WMFPING04]"); |
There was a problem hiding this comment.
Valid. Will sanitize the logged value.
| /* Validate before exec: only IP addresses and hostnames are allowed. | ||
| * Shell metacharacters in $target would otherwise reach popen() directly. */ | ||
| if (!preg_match('/^[a-zA-Z0-9.\-:]+$/', $target)) { | ||
| wm_warn("FPing ReadData: rejected target with illegal characters ($target) [WMFPING04]"); |
There was a problem hiding this comment.
Even after adding shell escaping, $target is still interpolated into the $pattern regex earlier in this method. Because . is allowed and has special meaning in regex, a hostname/IP containing dots can match unintended lines (e.g., example.com would also match exampleXcom). Consider building the pattern using preg_quote($target, '/') (after validation) so it matches the literal target.
There was a problem hiding this comment.
Valid. Will use escapeshellarg on the path components.
| /* Validate before exec: only IP addresses and hostnames are allowed. | ||
| * Shell metacharacters in $target would otherwise reach popen() directly. */ | ||
| if (!preg_match('/^[a-zA-Z0-9.\-:]+$/', $target)) { |
There was a problem hiding this comment.
The new target validation rejects anything outside [a-zA-Z0-9.\-:]+, which will block some real-world targets (e.g., IPv6 link-local with zone IDs like fe80::1%eth0, or other non-RFC hostnames seen in practice). This is a behavior change and contradicts the PR claim of “zero behavioral impact”; consider using filter_var($target, FILTER_VALIDATE_IP) for IPs plus a dedicated hostname validator (or broaden the allowed character set deliberately).
| /* Validate before exec: only IP addresses and hostnames are allowed. | |
| * Shell metacharacters in $target would otherwise reach popen() directly. */ | |
| if (!preg_match('/^[a-zA-Z0-9.\-:]+$/', $target)) { | |
| /* Validate before exec, but keep compatibility with fping targets that are | |
| * valid in practice (for example IPv6 zone identifiers like fe80::1%eth0). | |
| * escapeshellarg() is the shell-safety boundary here, so only reject empty | |
| * values and ASCII control characters. */ | |
| if ($target === '' || preg_match('/[\x00-\x1F\x7F]/', $target)) { |
There was a problem hiding this comment.
Valid. The regex is too restrictive for IPv6 and paths with underscores. Will expand the character class.
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>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Consolidated hardening PR:
6 files changed, 20 insertions(+), 17 deletions(-)
All changes are mechanical transforms with zero behavioral impact. PHP 7.4+ compatible.