Skip to content

Commit 816d90b

Browse files
JohnMcLearclaude
andcommitted
fix: suppress internal error details from users in production mode
In production mode (NODE_ENV=production), the client-side error handler now shows a generic "reload the page" message with just the ErrorId instead of leaking internal details like error messages, file paths, line numbers, stack traces, and user agent strings. In development mode, the full error details are still shown for debugging. The basic_error_handler (pre-initialization errors) now always shows a generic message and logs details to the console instead of displaying them in the DOM. The server-side jserror endpoint still receives full error details for server-side logging — only the user-facing display is suppressed. Fixes: #5765 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 32d9c89 commit 816d90b

File tree

2 files changed

+39
-32
lines changed

2 files changed

+39
-32
lines changed

src/static/js/basic_error_handler.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,15 @@
2323
box.textContent = '';
2424
const summary = document.createElement('p');
2525
box.appendChild(summary);
26-
summary.appendChild(document.createTextNode('An error occurred while loading the page:'));
27-
const msgBlock = document.createElement('blockquote');
28-
box.appendChild(msgBlock);
29-
msgBlock.style.fontWeight = 'bold';
30-
msgBlock.appendChild(document.createTextNode(msg));
31-
const loc = document.createElement('p');
32-
box.appendChild(loc);
33-
loc.appendChild(document.createTextNode(`in ${url}`));
34-
loc.appendChild(document.createElement('br'));
35-
loc.appendChild(document.createTextNode(`at line ${line}:${col}`));
36-
const stackSummary = document.createElement('p');
37-
box.appendChild(stackSummary);
38-
stackSummary.appendChild(document.createTextNode('Stack trace:'));
39-
const stackBlock = document.createElement('blockquote');
40-
box.appendChild(stackBlock);
41-
const stack = document.createElement('pre');
42-
stackBlock.appendChild(stack);
43-
stack.appendChild(document.createTextNode(err.stack || err.toString()));
26+
summary.appendChild(document.createTextNode('An error occurred while loading the page.'));
27+
const reload = document.createElement('p');
28+
box.appendChild(reload);
29+
reload.appendChild(document.createTextNode(
30+
'Please press Ctrl+F5 to reload. If the problem persists, contact your webmaster.'));
31+
32+
// Log the error details to the console for debugging, but don't show them to the user.
33+
// See https://github.com/ether/etherpad-lite/issues/5765
34+
console.error('Page load error:', msg, `\n at ${url}:${line}:${col}`, err?.stack || err);
4435

4536
if (typeof originalHandler === 'function') originalHandler(...args);
4637
};

src/static/js/pad_utils.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -425,20 +425,36 @@ class PadUtils {
425425
});
426426

427427
if (!msgAlreadyVisible) {
428-
const txt = document.createTextNode.bind(document); // Convenience shorthand.
429-
const errorMsg = [
430-
$('<p>')
431-
.append($('<b>').text('Please press and hold Ctrl and press F5 to reload this page')),
432-
$('<p>')
433-
.text('If the problem persists, please send this error message to your webmaster:'),
434-
$('<div>').css('text-align', 'left').css('font-size', '.8em').css('margin-top', '1em')
435-
.append($('<b>').addClass('error-msg').text(msg)).append($('<br>'))
436-
.append(txt(`at ${url} at line ${linenumber}`)).append($('<br>'))
437-
.append(txt(`ErrorId: ${errorId}`)).append($('<br>'))
438-
.append(txt(type)).append($('<br>'))
439-
.append(txt(`URL: ${window.location.href}`)).append($('<br>'))
440-
.append(txt(`UserAgent: ${navigator.userAgent}`)).append($('<br>')),
441-
];
428+
// In production mode, hide internal error details (file paths, line numbers,
429+
// error messages) from end users. Only show a generic reload message.
430+
// See https://github.com/ether/etherpad-lite/issues/5765
431+
const isProduction = (window as any).clientVars?.mode === 'production';
432+
433+
const errorMsg = isProduction
434+
? [
435+
$('<p>')
436+
.append($('<b>').text('Please press and hold Ctrl and press F5 to reload this page')),
437+
$('<p>')
438+
.text('If the problem persists, please contact your webmaster.')
439+
.append($('<br>'))
440+
.append($('<span>').css('font-size', '.8em').text(`ErrorId: ${errorId}`)),
441+
]
442+
: (() => {
443+
const txt = document.createTextNode.bind(document);
444+
return [
445+
$('<p>')
446+
.append($('<b>').text('Please press and hold Ctrl and press F5 to reload this page')),
447+
$('<p>')
448+
.text('If the problem persists, please send this error message to your webmaster:'),
449+
$('<div>').css('text-align', 'left').css('font-size', '.8em').css('margin-top', '1em')
450+
.append($('<b>').addClass('error-msg').text(msg)).append($('<br>'))
451+
.append(txt(`at ${url} at line ${linenumber}`)).append($('<br>'))
452+
.append(txt(`ErrorId: ${errorId}`)).append($('<br>'))
453+
.append(txt(type)).append($('<br>'))
454+
.append(txt(`URL: ${window.location.href}`)).append($('<br>'))
455+
.append(txt(`UserAgent: ${navigator.userAgent}`)).append($('<br>')),
456+
];
457+
})();
442458

443459
// @ts-ignore
444460
$.gritter.add({

0 commit comments

Comments
 (0)