diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index b1f01ab72..bc82c5e8e 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -1383,6 +1383,20 @@ our @options = ( type => $types{boolean}, category => 'logging', }, + { + name => 'ZM_LOG_BROWSER_EXTENSIONS', + default => 'no', + description => 'Log Javascript errors and CSP violations from browser extensions', + help => q` + Browser extensions (ad blockers, password managers, etc.) inject scripts into + every page. Their Javascript errors and Content-Security-Policy violations are + not ZoneMinder's code and normally just spam the web_js log, so by default they + are ignored. Enable this if you want to see when a browser extension is touching + the ZoneMinder tab, at the cost of noisier logs. + `, + type => $types{boolean}, + category => 'logging', + }, { name => 'ZM_LOG_DEBUG', default => 'no', diff --git a/web/js/logger.js b/web/js/logger.js index 1c081d9e5..45b5e8cc4 100644 --- a/web/js/logger.js +++ b/web/js/logger.js @@ -36,14 +36,21 @@ if (!window.console) { // Browser extensions (ad blockers, password managers, etc.) inject scripts // into every page; their errors and CSP violations are not ZoneMinder's and -// would otherwise spam the log. Ignore anything sourced from an extension. +// would otherwise spam the log. Ignore anything sourced from an extension, +// unless ZM_LOG_BROWSER_EXTENSIONS is enabled (useful to detect a plugin +// touching the ZoneMinder tab). +// ZM_LOG_BROWSER_EXTENSIONS is emitted as the string '0'/'1' (boolean config), +// matching the ZM_LOG_INJECT convention above. +const logExtensionSources = + (typeof ZM_LOG_BROWSER_EXTENSIONS !== 'undefined') && (ZM_LOG_BROWSER_EXTENSIONS !== '0'); + function isExtensionSource(url) { return (typeof url === 'string') && /^(moz-extension|chrome-extension|safari-web-extension|safari-extension|webkit-masked-url)(:|$)/.test(url); } window.onerror = function(message, url, line, col, error) { - if (isExtensionSource(url)) return; + if (!logExtensionSources && isExtensionSource(url)) return; if (!message || message === 'Script error.') { message = 'Script error (no details available, possibly cross-origin)'; } @@ -55,7 +62,7 @@ window.onerror = function(message, url, line, col, error) { }; window.addEventListener("securitypolicyviolation", function logCSP(evt) { - if (isExtensionSource(evt.sourceFile) || isExtensionSource(evt.blockedURI)) return; + if (!logExtensionSources && (isExtensionSource(evt.sourceFile) || isExtensionSource(evt.blockedURI))) return; const level = evt.disposition == "enforce" ? "ERR" : "DBG"; let message = evt.blockedURI + " violated CSP " + evt.violatedDirective;