[pkg-nagios-changes] [Git][nagios-team/nagvis][master] 4 commits: New upstream version 1.10.7
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Fri Oct 30 14:40:31 GMT 2026
Bas Couwenberg pushed to branch master at Debian Nagios Maintainer Group / nagvis
Commits:
59e23ea3 by Bas Couwenberg at 2026-10-30T15:37:00+01:00
New upstream version 1.10.7
- - - - -
48431231 by Bas Couwenberg at 2026-10-30T15:37:06+01:00
Update upstream source from tag 'upstream/1.10.7'
Update to upstream version '1.10.7'
with Debian dir 6fa41e25827c04af557112ea331aa36ba930ae3d
- - - - -
112cec0e by Bas Couwenberg at 2026-10-30T15:37:29+01:00
New upstream release.
- - - - -
bd9f92da by Bas Couwenberg at 2026-10-30T15:38:10+01:00
Set distribution to unstable.
- - - - -
11 changed files:
- ChangeLog
- debian/changelog
- package-lock.json
- share/frontend/nagvis-js/js/ElementContext.js
- share/frontend/nagvis-js/js/ElementHover.js
- share/frontend/nagvis-js/js/ElementLabel.js
- share/frontend/nagvis-js/js/frontend.js
- share/frontend/nagvis-js/js/nagvis.js
- share/server/core/defines/global.php
- share/userfiles/templates/default.context.html
- share/userfiles/templates/default.header.html
Changes:
=====================================
ChangeLog
=====================================
@@ -1,3 +1,9 @@
+1.10.7
+ * FIX: Special characters in hover menu child rows are no longer shown as HTML entities (#459)
+ * FIX: NagVis logo link now opens nagvis.org in a new tab, so a Content-Security-Policy no longer blocks it when NagVis is embedded in a frame (e.g. the Checkmk NagVis snapin)
+ * FIX: Prevent XSS via object names in context menus
+ * FIX: Prevent XSS via check output and object names in hover menus and labels (CVSS: 7.3) CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:H/VI:H/VA:H/SC:N/SI:L/SA:N. HTML in check output, notes or object names is now shown as text instead of being rendered.
+
1.10.6
* FEAT: The "editHtml" permission can now be granted to roles via the role management GUI, instead of only being available to administrators (#452)
* FIX: Non-admin roles (e.g. Managers) can edit maps again - the editHtml permission is now only required to change HTML content, not for every map modification (#452)
=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+nagvis (1:1.10.7-1) unstable; urgency=medium
+
+ * Team upload.
+ * New upstream release.
+
+ -- Bas Couwenberg <sebastic at debian.org> Fri, 30 Oct 2026 15:38:00 +0100
+
nagvis (1:1.10.6-1) unstable; urgency=medium
* Team upload.
=====================================
package-lock.json
=====================================
@@ -170,29 +170,43 @@
}
},
"node_modules/@humanfs/core": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
- "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
+ "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
"dev": true,
"license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/types": "^0.15.0"
+ },
"engines": {
"node": ">=18.18.0"
}
},
"node_modules/@humanfs/node": {
- "version": "0.16.7",
- "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
- "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
+ "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@humanfs/core": "^0.19.1",
+ "@humanfs/core": "^0.19.2",
+ "@humanfs/types": "^0.15.0",
"@humanwhocodes/retry": "^0.4.0"
},
"engines": {
"node": ">=18.18.0"
}
},
+ "node_modules/@humanfs/types": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
+ "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
"node_modules/@humanwhocodes/module-importer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@@ -306,9 +320,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
- "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
+ "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -769,9 +783,9 @@
"license": "ISC"
},
"node_modules/js-yaml": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
- "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz",
+ "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==",
"dev": true,
"funding": [
{
=====================================
share/frontend/nagvis-js/js/ElementContext.js
=====================================
@@ -24,6 +24,21 @@
const g_context_templates = {};
let g_context_open = null;
+// The custom macros come from the backend definitions in the main config, which
+// only admins can edit, and are meant to hold HTML or URLs
+const g_context_raw_macros = new Set(["custom_1", "custom_2", "custom_3"]);
+
+// Makes a context macro value safe for the menu HTML as well as for JS strings
+// in inline handlers and javascript: URLs. The browser decodes HTML entities
+// (and the percent encoding of javascript: URLs) before running the JS, so
+// backslashes, quotes and percent signs are JS escaped first. "%20" is kept for
+// the space encoded pnp_* macros.
+function escapeContextMacro(name, value) {
+ if (!value) return "";
+ if (g_context_raw_macros.has(name)) return value;
+ return htmlspecialchars(String(value).replace(/[\\'"]|%(?!20)/g, (c) => "\\x" + c.charCodeAt(0).toString(16)));
+}
+
// Hides the currently open context menu
function contextHide() {
if (g_context_open !== null) g_context_open.hide();
@@ -369,9 +384,10 @@ const ElementContext = Element.extend({
}
oSectionMacros = null;
- // Loop and replace all normal macros
+ // Loop and replace all normal macros. The values are object derived, so
+ // escape them to prevent XSS when the menu is inserted via innerHTML.
this.template_html = this.template_html.replace(/\[(\w*)\]/g, function () {
- return oMacros[arguments[1]] || "";
+ return escapeContextMacro(arguments[1], oMacros[arguments[1]]);
});
oMacros = null;
}
=====================================
share/frontend/nagvis-js/js/ElementHover.js
=====================================
@@ -26,6 +26,23 @@ const g_hover_template_childs = {};
const g_hover_urls = {};
let g_hover_open = null;
+// State output macros are pre-encoded by the server and get their own escaping
+const g_hover_state_output_macros = new Set(["obj_output", "obj_summary_output", "obj_perfdata"]);
+
+// The custom macros come from the backend definitions in the main config, which
+// only admins can edit, and are meant to hold HTML or URLs
+const g_hover_raw_macros = new Set(["custom_1", "custom_2", "custom_3"]);
+
+// Escapes a hover macro value before it is inserted into the menu HTML. Every
+// macro is escaped except the language strings and the custom macros, so newly
+// added macros are safe by default.
+function escapeHoverMacro(name, value) {
+ if (value === null || value === undefined) return "";
+ if (name.startsWith("lang_") || g_hover_raw_macros.has(name)) return value;
+ if (g_hover_state_output_macros.has(name)) return escapeStateOutput(value);
+ return htmlspecialchars(value);
+}
+
// Hides the currently open hover menu
function hoverHide() {
if (g_hover_open !== null) g_hover_open.hide();
@@ -500,7 +517,9 @@ const ElementHover = Element.extend({
// Replace all normal macros
template_html = template_html.replace(/\[(\w*)\]/g, function () {
- return htmlspecialchars(oMacros[arguments[1]] || "");
+ // The child display_name is pre-encoded by the server just like the output
+ if (arguments[1] === "obj_display_name") return escapeStateOutput(oMacros.obj_display_name);
+ return escapeHoverMacro(arguments[1], oMacros[arguments[1]]);
});
return template_html;
},
@@ -577,8 +596,9 @@ const ElementHover = Element.extend({
// not be mistaken for an unknown macro and dropped. Keep the original
// "[name]" text for tokens that are not actual macros, while still
// replacing defined macros that legitimately hold an empty value.
+ // All values are escaped to prevent XSS via check output.
template_html = template_html.replace(/\[(\w*)\]/g, function (match, name) {
- return Object.prototype.hasOwnProperty.call(oMacros, name) ? oMacros[name] : match;
+ return Object.prototype.hasOwnProperty.call(oMacros, name) ? escapeHoverMacro(name, oMacros[name]) : match;
});
return template_html;
},
@@ -719,7 +739,8 @@ const ElementHover = Element.extend({
// Loop and replace all normal macros
this.template_html = this.template_html.replace(/\[(\w*)\]/g, function () {
- return oMacros[arguments[1]] || "[" + arguments[1] + "]";
+ const name = arguments[1];
+ return oMacros[name] ? escapeHoverMacro(name, oMacros[name]) : "[" + name + "]";
});
// Re-add the clean child code
=====================================
share/frontend/nagvis-js/js/ElementLabel.js
=====================================
@@ -37,13 +37,17 @@ const ElementLabel = Element.extend({
objName = this.obj.conf.name;
}
- this.label_text = this.label_text.replace(getRegEx("name", "\\[name\\]", "g"), objName);
- this.label_text = this.label_text.replace(getRegEx("alias", "\\[alias\\]", "g"), this.obj.conf.alias);
+ // The label is rendered as HTML, so object derived values are escaped
+ const name = htmlspecialchars(objName);
+ const alias = htmlspecialchars(this.obj.conf.alias);
+ this.label_text = this.label_text.replace(getRegEx("name", "\\[name\\]", "g"), () => name);
+ this.label_text = this.label_text.replace(getRegEx("alias", "\\[alias\\]", "g"), () => alias);
if (this.obj.conf.type == "service") {
+ const service_description = htmlspecialchars(this.obj.conf.service_description);
this.label_text = this.label_text.replace(
getRegEx("service_description", "\\[service_description\\]", "g"),
- this.obj.conf.service_description
+ () => service_description
);
}
}
@@ -124,15 +128,18 @@ const ElementLabel = Element.extend({
// Replace static macros in label_text when needed
if (text && text !== "") {
- text = text.replace(getRegEx("output", "\\[output\\]", "g"), this.obj.conf.output);
+ const output = escapeStateOutput(this.obj.conf.output);
+ text = text.replace(getRegEx("output", "\\[output\\]", "g"), () => output);
if (this.obj.conf.type == "service" || this.obj.conf.type == "host") {
- text = text.replace(getRegEx("perfdata", "\\[perfdata\\]", "g"), this.obj.conf.perfdata);
+ const perfdata = escapeStateOutput(this.obj.conf.perfdata);
+ text = text.replace(getRegEx("perfdata", "\\[perfdata\\]", "g"), () => perfdata);
}
}
+ // Drop a trailing entity or tag which has been cut in half by the truncation
if (this.obj.conf.label_maxlen > 0 && text.length > this.obj.conf.label_maxlen)
- text = text.substr(0, this.obj.conf.label_maxlen - 2) + "...";
+ text = text.substr(0, this.obj.conf.label_maxlen - 2).replace(/&[^;\s]*$|<[^>]*$/, "") + "...";
return text;
},
=====================================
share/frontend/nagvis-js/js/frontend.js
=====================================
@@ -285,6 +285,16 @@ function showAckDialog(map_name, objectId) {
);
}
+// Reloads the current automap with the given object as root. The object name
+// is looked up here instead of being put into the context template, because
+// HTML escaping does not protect a value inside inline JS.
+function makeRootObject(map_name, objectId) {
+ const obj = getMapObjByDomObjId(objectId);
+ if (!obj) return;
+ window.location =
+ "index.php?mod=Map&act=view&show=" + escapeUrlValues(map_name) + getViewParams({ root: obj.conf.name }, true);
+}
+
// Handles manual map object update triggered by e.g. the context menu
function refreshMapObject(event, objectId, only_state) {
if (typeof only_state === "undefined") only_state = true;
=====================================
share/frontend/nagvis-js/js/nagvis.js
=====================================
@@ -787,7 +787,23 @@ function htmlspecialchars(sStr) {
'"': """,
"'": "'"
};
- return sStr.replace(/[&<>"']/g, (match) => map[match]);
+ if (sStr === null || sStr === undefined) return "";
+ return String(sStr).replace(/[&<>"']/g, (match) => map[match]);
+}
+
+/**
+ * Escapes state output (output/summary_output/perfdata) which has already been
+ * pre-encoded by the server (escapeStringForJson). Neutralises HTML tags while
+ * keeping the server generated <br /> line breaks and entities intact.
+ *
+ * "&" is not escaped, so the result is only safe in element content and in
+ * quoted attributes, not in unquoted attributes or inline JS.
+ */
+function escapeStateOutput(sStr) {
+ return (sStr || "")
+ .replace(/</g, "<")
+ .replace(/>/g, ">")
+ .replace(/<br \/>/g, "<br />");
}
/**
=====================================
share/server/core/defines/global.php
=====================================
@@ -24,7 +24,7 @@
*****************************************************************************/
// NagVis Version
-const CONST_VERSION = '1.10.6';
+const CONST_VERSION = '1.10.7';
// Set PHP error handling to standard level
// Different levels for php versions below 5.1 because PHP 5.1 reports
=====================================
share/userfiles/templates/default.context.html
=====================================
@@ -1,7 +1,7 @@
<ul>
<!-- BEGIN automap_not_root -->
<!-- BEGIN host_or_shape -->
- <li><a href="javascript:window.location='index.php?mod=Map&act=view&show=[map_name]'+getViewParams({'root':'[name]'}, true);">[lang_make_root]</a></li>
+ <li><a href="#" onClick="makeRootObject('[map_name]', '[obj_id]');contextHide();return false">[lang_make_root]</a></li>
<!-- END host_or_shape -->
<!-- END automap_not_root -->
=====================================
share/userfiles/templates/default.header.html
=====================================
@@ -6,7 +6,7 @@
<ul class="head">
<div id="sidetoggle" onclick="toggleSidebar(true)"><img src="{$pathImages}/internal/sidebar_open.png" /></div>
<li class="toggle"><a href="#" onclick="toggleHeader(true)" title="Hide header menu"><</a></li>
- <li class="logo"><a href="https://www.nagvis.org/"><img src="{$pathImages}/internal/logo_small.png" alt="NagVis" /></a></li>
+ <li class="logo"><a href="https://www.nagvis.org/" target="_blank" rel="noopener noreferrer"><img src="{$pathImages}/internal/logo_small.png" alt="NagVis" /></a></li>
<li class="dropdown">
<span id="views-ddheader" onclick="ddMenuToggle(event, 'views')">{$langOpen}</span>
{template headMaps maps pathBase currentMap indent=1}
View it on GitLab: https://salsa.debian.org/nagios-team/nagvis/-/compare/3803149830dac4c21d6e529111684acde755d235...bd9f92da44365a5c9b4c40bb313dc4d295019b45
--
View it on GitLab: https://salsa.debian.org/nagios-team/nagvis/-/compare/3803149830dac4c21d6e529111684acde755d235...bd9f92da44365a5c9b4c40bb313dc4d295019b45
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-nagios-changes/attachments/20261030/143f1655/attachment-0001.htm>
More information about the pkg-nagios-changes
mailing list