Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# +-------------------------------------------------------------------------+
# | Copyright (C) 2004-2026 The Cacti Group |
# +-------------------------------------------------------------------------+
# | Cacti: The Complete RRDtool-based Graphing Solution |
# +-------------------------------------------------------------------------+
# | http://www.cacti.net/ |
# +-------------------------------------------------------------------------+

# No composer entry: the plugin ships no composer.json, and its tests run from
# a plain PHP CLI by design.
Comment on lines +9 to +10

version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "develop"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
groups:
github-actions:
patterns:
- "*"
commit-message:
prefix: "ci"
include: "scope"
59 changes: 59 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# +-------------------------------------------------------------------------+
# | Copyright (C) 2004-2026 The Cacti Group |
# +-------------------------------------------------------------------------+
# | Cacti: The Complete RRDtool-based Graphing Solution |
# +-------------------------------------------------------------------------+
# | http://www.cacti.net/ |
# +-------------------------------------------------------------------------+
#
# CodeQL has no PHP analysis, so this covers the plugin JavaScript only. The PHP is
# covered by the syntax and integration jobs in plugin-ci-workflow.yml.

name: "CodeQL"

on:
push:
branches: [main, develop]
paths-ignore:
- "**/*.md"
pull_request:
branches: [main, develop]
paths-ignore:
- "**/*.md"
schedule:
- cron: "30 1 * * 1"
workflow_dispatch:

concurrency:
group: codeql-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["javascript-typescript"]
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Initialize CodeQL
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3
with:
category: "/language:${{ matrix.language }}"
53 changes: 50 additions & 3 deletions .github/workflows/plugin-ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,54 @@ on:
- main
- develop

permissions:
contents: read

jobs:
# The plugin ships tests that nothing ran: three files under tests/ that pass
# from a plain PHP CLI. They cover request-variable output escaping, which is
# the class of defect most likely to regress here.
unit-test:
name: Standalone test suite
runs-on: ubuntu-latest
steps:
- name: Checkout monitor Plugin
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5

- name: Install PHP
uses: shivammathur/setup-php@b604ade2a87db23f8871b7182e69ec5e75effb45 # v2
with:
php-version: '8.1'
tools: composer

- name: Install dev dependencies
run: composer install --prefer-dist --no-progress --no-interaction --no-plugins --no-scripts

- name: Run the test suite
run: composer test

# compat = 1.2.15 implies Cacti 1.2.x, which requires PHP 8.0. The matrix
# below starts at 8.1, so it cannot catch syntax the declared floor rejects.
syntax-floor:
name: PHP 8.0 syntax floor
runs-on: ubuntu-latest
steps:
- name: Checkout monitor Plugin
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5

- name: Install PHP 8.0
uses: shivammathur/setup-php@b604ade2a87db23f8871b7182e69ec5e75effb45 # v2
with:
php-version: '8.0'

- name: Lint every PHP file
run: |
if find . -path ./vendor -prune -o -name '*.php' -print \
| xargs -n1 php -l 2>&1 | grep -iv 'no syntax errors detected'; then
echo "Syntax errors found at the declared PHP floor"
exit 1
fi

integration-test:
runs-on: ${{ matrix.os }}

Expand Down Expand Up @@ -61,18 +108,18 @@ jobs:

steps:
- name: Checkout Cacti
uses: actions/checkout@v5
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
repository: Cacti/cacti
path: cacti

- name: Checkout Monitor Plugin
uses: actions/checkout@v5
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
path: cacti/plugins/monitor

- name: Install PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@b604ade2a87db23f8871b7182e69ec5e75effb45 # v2
with:
php-version: ${{ matrix.php }}
extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@
locales/po/*.mo
vendor/
.omc/

# Lockfile is not committed: the plugin declares a range, and thold does the same.
composer.lock
/vendor/
.phpunit.result.cache
21 changes: 21 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "cacti/plugin_monitor",
"description": "Monitor Plugin for Cacti",
"type": "cacti-plugin",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=8.0"
},
"require-dev": {
"pestphp/pest": "^2"
},
Comment on lines +6 to +11
"config": {
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"scripts": {
"test": "pest",
"test:integration": "pest tests/Integration"
}
}
8 changes: 8 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true" beStrictAboutOutputDuringTests="false">
<testsuites>
<testsuite name="Integration">
<directory>./tests/Integration</directory>
</testsuite>
</testsuites>
</phpunit>
49 changes: 49 additions & 0 deletions tests/Integration/OutputEscapingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
+-------------------------------------------------------------------------+
| Request values reach hidden inputs and query strings. These match the |
| source text rather than running the pages, so they detect an escaping |
| call being deleted; they prove nothing about runtime behaviour. The |
| pages chdir() to the Cacti root and include auth.php, so exercising them |
| needs a live install. |
+-------------------------------------------------------------------------+
*/

$root = dirname(__DIR__, 2);

dataset('escaped_outputs', [
['monitor_controller.php', "html_escape(get_request_var('downhosts'))"],
['monitor_controller.php', "html_escape(get_request_var('mute'))"],
['monitor_controller.php', "html_escape(get_request_var('tree'))"],
['monitor_controller.php', "html_escape(get_request_var('site'))"],
['monitor_controller.php', "html_escape(get_request_var('template'))"],
['monitor_controller.php', "html_escape(get_request_var('size'))"],
['monitor_controller.php', "html_escape(get_request_var('trim'))"],
['monitor_render.php', "rawurlencode(get_request_var('rfilter'))"],
]);

it('escapes request values before printing them', function (string $file, string $pattern) use ($root) {
expect(file_get_contents($root . '/' . $file))->toContain($pattern);
})->with('escaped_outputs');
Comment on lines +27 to +29

dataset('raw_reuse', [
['monitor_controller.php', "get_request_var('tree') . '\"></td>'"],
['monitor_controller.php', "get_request_var('site') . '\"></td>'"],
['monitor_controller.php', "get_request_var('template') . '\"></td>'"],
['monitor_controller.php', "get_request_var('size') . '\"></td>'"],
['monitor_controller.php', "get_request_var('trim') . '\"></td>'"],
['monitor_render.php', "monitor.php?rfilter=' . get_request_var('rfilter')"],
]);

it('never concatenates a raw request value into markup', function (string $file, string $pattern) use ($root) {
expect(file_get_contents($root . '/' . $file))->not->toContain($pattern);
})->with('raw_reuse');

it('escapes a payload that would break out of a hidden input', function () {
$payload = '" autofocus onfocus="alert(1)';
$escaped = htmlspecialchars($payload, ENT_QUOTES, 'UTF-8');

expect($escaped)->not->toContain('"')->and($escaped)->toContain('&quot;');
});
41 changes: 0 additions & 41 deletions tests/Integration/test_monitor_request_output_wiring.php

This file was deleted.

14 changes: 14 additions & 0 deletions tests/Pest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
*/

uses()->beforeEach(function () {
$GLOBALS['__test_sql'] = [];
$GLOBALS['__test_settings'] = [];
test_set_request([]);
})->in(__DIR__);
Loading
Loading