fix: multiple critical bugs in frontend

- sidebar: fix library/tag selection event handlers not firing (callbacks never invoked)
- sidebar: fix handleSelectLibrary always passing empty string instead of library id
- dashboard: fix tag filter not persisting when navigating from document view
- app: fix XSS vulnerability in showToast (API error messages not escaped)
- app: fix XSS vulnerability in confirmDelete modal message
- document: fix path traversal risk in export filename
This commit is contained in:
Hiro
2026-03-28 12:06:16 +00:00
parent af7f639c20
commit 461a17bc45
4 changed files with 80 additions and 43 deletions

View File

@@ -77,18 +77,27 @@ class App {
const container = document.getElementById('toast-container');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
const escapedMessage = this.escapeHtml(message);
toast.innerHTML = `
<span class="toast-message">${message}</span>
<span class="toast-message">${escapedMessage}</span>
<button class="toast-close" onclick="this.parentElement.remove()">✕</button>
`;
container.appendChild(toast);
setTimeout(() => toast.remove(), 4000);
}
escapeHtml(str) {
if (!str) return '';
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
async confirmDelete(message) {
return new Promise((resolve) => {
const backdrop = document.createElement('div');
backdrop.className = 'modal-backdrop';
const escapedMessage = this.escapeHtml(message);
backdrop.innerHTML = `
<div class="modal">
<div class="modal-header">
@@ -96,7 +105,7 @@ class App {
<h3>Confirm Delete</h3>
</div>
<div class="modal-body">
<p>${message}</p>
<p>${escapedMessage}</p>
</div>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancel-btn">Cancel</button>