Issues derived from SECURITY-AUDIT.md. Do not push to GitHub until contrib-ledger gate passes.
Priority: medium (blocker for security tests)
Labels: refactor, tech-debt
Branch: refactor/1-shell-command-seams
Evidence: WeatherMapDataSource_fping.php:103; WeatherMapDataSource_rrd.php:296–325
Acceptance criteria:
-
src/Shell/FpingRunner.phpwraps popen call; accepts pre-built command string -
src/Rrd/RrdCommandBuilder.phpassembles rrdtool command string from typed args - Both classes instantiable without Cacti bootstrap
- PHPStan level 6 passes on
src/
Dependencies: none
Priority: medium
Labels: security
Branch: security/2-escapeshellarg-fping-target
Evidence: lib/datasources/WeatherMapDataSource_fping.php:103 (WM-CMD-01)
Acceptance criteria:
-
$targetvalidated withfilter_var($target, FILTER_VALIDATE_IP)or strict hostname regex before use -
escapeshellarg($target)applied in command string -
src/Shell/FpingRunner.phpseam extracted and unit-tested - Security test WM-CMD-01 passes (todo removed)
- Targets that fail IP/hostname validation are rejected with a logged warning
Dependencies: Issue #1
Priority: low
Labels: security, tech-debt
Branch: security/3-fix-rrd-arg-quoting
Evidence: lib/datasources/WeatherMapDataSource_rrd.php:325, 429 (WM-CMD-02)
Acceptance criteria:
- Manual double-quote wrapping replaced with
escapeshellarg()per argument -
$rrdfilevalidated as absolute filesystem path with no shell metacharacters -
src/Rrd/RrdCommandBuilder.phpseam extracted and unit-tested - Security test WM-CMD-02 passes (todo removed)
Dependencies: Issue #1
Priority: low
Labels: security, tech-debt
Branch: security/4-sanitize-conffile-backslash
Evidence: lib/editor.inc.php:232–246 (WM-PATH-01)
Acceptance criteria:
-
wm_editor_sanitize_conffilerejects filenames containing\ - Path traversal test WM-PATH-01 (backslash case) todo removed
- Existing positive test cases remain green
Dependencies: none
Priority: medium
Labels: security, tech-debt
Branch: security/5-validate-editor-action
Evidence: weathermap-cacti-plugin-editor.php:91 — $action = get_nfilter_request_var('action') without allowed-list validation
Acceptance criteria:
-
$actionvalidated against an explicit list of valid editor action strings - Unknown actions produce a logged warning and abort
- PHPStan level 6 passes
Dependencies: none
Priority: low
Labels: refactor, tech-debt
Branch: refactor/6-mapname-validator-class
Evidence: lib/editor.inc.php:232–246
Acceptance criteria:
-
src/Config/MapnameValidator.phpwrapswm_editor_sanitize_conffilelogic - All existing sanitization cases covered by unit tests
- PHPStan level 6 passes
Dependencies: none
Priority: medium
Labels: ci
Branch: ci/7-pest-phpstan-workflow
Acceptance criteria:
-
.github/workflows/test.ymlrunscomposer testandcomposer analyse - PHPStan level 6 clean on
src/andtests/ - Actions pinned to full commit SHA
Dependencies: Issues #1–#5
Priority: medium
Labels: security, docs
Branch: docs/8-editor-action-audit
Evidence: editor action variable not fully traced in this audit
Acceptance criteria:
- All action values and their code paths documented
- Any state-changing actions that lack CSRF or auth checks identified and filed as separate issues
Dependencies: none
Priority: low
Labels: bug, tech-debt
Branch: feature/9-legend-hide-zero
Evidence: lib/WeatherMap.class.php DrawLegend_Classic() — the key_hidezero_* check tested isset($colours['0_0']), but $colours is reindexed to a plain list by usort() just above, so the string key never existed and the option had silently stopped working. The dead branch was removed during the PHPStan level 8 pass.
Acceptance criteria:
- Detect the zero/zero scale entry against the post-sort list (e.g. match
bottom == 0 && top == 0) -
key_hidezero_<scale>again drops that entry from the rendered legend - Unit test covers both the hidden and shown cases
Dependencies: none
Issue #10: refactor: provision schema through api_plugin_db_table_create()/api_plugin_db_add_column()
Priority: low
Labels: refactor, tech-debt
Branch: refactor/10-schema-plugin-db-api
Evidence: includes/database.php — weathermap_setup_table() still provisions its tables with raw CREATE TABLE/ALTER TABLE ... ADD COLUMN statements rather than the idempotent Cacti schema API mandated by .github/copilot-instructions.md ("Plugin table-creation API"). The code was relocated verbatim from setup.php in the schema-relocation PR; converting it to the API is deliberately deferred to keep that move behaviour-preserving.
Acceptance criteria:
- Each
weathermap_*table is defined throughapi_plugin_db_table_create() - Incremental column additions use
api_plugin_db_add_column() - Only genuine data migrations (duplicate-row cleanup, sortorder/filehash backfills) remain as prepared
db_execute*()calls - Install and upgrade paths both run the same idempotent provisioning
- Existing install/upgrade unit tests remain green
Dependencies: none