-
Type:
Incident report
-
Resolution: Unresolved
-
Priority:
Trivial
-
None
-
Affects Version/s: 7.0.31, 8.0.0rc1
-
Component/s: Frontend (F)
-
None
-
Environment:Zabbix 7.0.30 and 7.0.31 frontend (reproduced), nginx + PHP 8.5 / Apache + PHP 8.3, Chrome 155 and Safari 26. The same code is present in release/7.2, release/7.4 and master (8.0.0rc2).
Steps to reproduce
- Import the attached minimal template zbx_test_template_clone_jsonp.yaml (one macro, description "Packets > x Threshold ???").
- Data collection -> Templates -> open the template form.
- Press Clone.
Result
The dialog is replaced by "Unexpected server error." and the browser console shows:
SyntaxError: Failed to execute 'appendChild' on 'Node': Unexpected token ':'
at DOMEval (jsLoader.php ...)
at jQuery.globalEval
at text script
at ajaxConvert
The server actually answers HTTP 200 with a valid JSON body (checked in the web server access log and in the network tab). Nothing is written to the PHP error log.
Expected result
The "New template" clone form opens.
Root cause
Overlay.prototype.load() (ui/js/class.overlay.js) posts the dialog parameters with {{jQuery.ajax(
{type: 'post', dataType: 'json', data: options})}}. Forms such as template.edit and host.edit pass the whole form as a JSON string (PopUp('template.edit', JSON.stringify(parameters), ...)).
jQuery's built-in "json jsonp" prefilter treats any string request body that matches /(=)?(?=&|$)|??/ as a JSONP request (jquery.js, jQuery.ajaxPrefilter("json jsonp", ...)). It then:
- rewrites the matched text in the body to a generated callback name - the request actually sent contains "description":"Packets > x Threshold jQuery36008635464392983059_1791885867967?",
- sends Accept: text/javascript, application/javascript, ...,
- evaluates the JSON response as a script, which fails on the first :.
So any macro description, macro value, tag, template/host description or value map text that contains ?? (or =? at the end of the string) breaks Clone of that object. Real-world trigger: a vendor template with a macro description "Packets > x Threshold ???".
Overlay requests are same-origin POSTs and never JSONP, so JSONP auto-detection should be disabled explicitly.
Fix
Add jsonp: false to the ajax options in Overlay.prototype.load() (patch attached, applies to release/7.0 and master):
this.xhr = jQuery.ajax({ url: url.getUrl(), type: 'post', dataType: 'json', + jsonp: false, data: options });
Verified on 7.0.30: with the patch, Clone opens the form, the macro description keeps "???" and Add creates the template.
Workaround
Remove "??" from the macro description before cloning.