Skip to content

Commit 7394e09

Browse files
hardening: replace eval callback execution in autocomplete handling
Refs #268 Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
1 parent 6902d91 commit 7394e09

4 files changed

Lines changed: 76 additions & 1 deletion

File tree

.github/workflows/plugin-ci-workflow.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,16 @@ jobs:
187187
echo "Syntax errors found!"
188188
exit 1
189189
fi
190+
191+
- name: Run Plugin Regression Tests
192+
run: |
193+
cd ${{ github.workspace }}/cacti/plugins/syslog
194+
if [ -d tests/regression ]; then
195+
for test in tests/regression/*.php; do
196+
[ -f "$test" ] || continue
197+
php "$test"
198+
done
199+
fi
190200
191201

192202
- name: Run Cacti Poller

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
--- develop ---
44

55
* issue#250: Fix date filter persistence by validating before shift_span detection
6+
* issue#260: Replace eval-based callback execution in autocomplete handling
67
* issue: Making changes to support Cacti 1.3
78
* issue: Don't use MyISAM for non-analytical tables
89
* issue: The install advisor for Syslog was broken in current Cacti releases

js/functions.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,25 @@ function initSyslogReports() {
567567
* Autocomplete Form Callback Functions
568568
* ======================================================================== */
569569

570+
/**
571+
* Validate and invoke a named callback function specified as a string
572+
* @param {string} onChange - Name of the global function to call (e.g. 'myCallback')
573+
*/
574+
function runSyslogAutocompleteOnChange(onChange) {
575+
if (typeof onChange !== 'string') {
576+
return;
577+
}
578+
579+
var callbackName = onChange.trim().replace(/\(\)\s*$/, '');
580+
if (!callbackName.match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) {
581+
return;
582+
}
583+
584+
if (typeof window[callbackName] === 'function') {
585+
window[callbackName]();
586+
}
587+
}
588+
570589
/**
571590
* Initialize autocomplete for form dropdown fields
572591
* @param {string} formName - The name of the form field
@@ -591,7 +610,7 @@ function initSyslogAutocomplete(formName, callback, onChange) {
591610
$('#' + formName).val(ui.item.value);
592611
}
593612
if (onChange) {
594-
eval(onChange);
613+
runSyslogAutocompleteOnChange(onChange);
595614
}
596615
}
597616
}).css('border', 'none').css('background-color', 'transparent');
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
$javascript = file_get_contents(dirname(__DIR__, 2) . '/js/functions.js');
4+
5+
if ($javascript === false) {
6+
fwrite(STDERR, "Failed to load js/functions.js\n");
7+
exit(1);
8+
}
9+
10+
if (strpos($javascript, 'eval(') !== false) {
11+
fwrite(STDERR, "Unsafe eval() callback execution is still present.\n");
12+
exit(1);
13+
}
14+
15+
if (!preg_match('/function\s+runSyslogAutocompleteOnChange\s*\(\s*onChange\s*\)/', $javascript)) {
16+
fwrite(STDERR, "Safe autocomplete callback helper is missing.\n");
17+
exit(1);
18+
}
19+
20+
if (strpos($javascript, "if (!callbackName.match(/^[A-Za-z_$][A-Za-z0-9_$]*$/))") === false) {
21+
fwrite(STDERR, "Autocomplete callback name validation is missing.\n");
22+
exit(1);
23+
}
24+
25+
$hasCallbackTypeCheck = preg_match(
26+
'/if\s*\(\s*typeof\s+window\s*\[\s*callbackName\s*\]\s*===\s*[\'"]{1}function[\'"]{1}\s*\)/',
27+
$javascript
28+
) === 1;
29+
30+
$hasCallbackInvocation = preg_match(
31+
'/window\s*\[\s*callbackName\s*\]\s*\(/',
32+
$javascript
33+
) === 1;
34+
35+
if (!$hasCallbackTypeCheck || !$hasCallbackInvocation) {
36+
fwrite(STDERR, "Expected function-reference callback execution is missing.\n");
37+
exit(1);
38+
}
39+
40+
if (strpos($javascript, 'runSyslogAutocompleteOnChange(onChange);') === false) {
41+
fwrite(STDERR, "Autocomplete select handler is not using safe callback execution.\n");
42+
exit(1);
43+
}
44+
45+
echo "issue260_remove_eval_callback_test passed\n";

0 commit comments

Comments
 (0)