fix: address bug review findings

- Debounce MutationObserver (200ms) and scope to #modelGrid when available
- Sanitize data.updated via parseInt before innerHTML to prevent XSS
- Guard pagination against page_size=0 (division by zero) and negative values
- Reject non-POST requests on /api/lm-extra/fetch-stats (state-mutating)
- Early return in upsert_batch for empty rows list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 14:48:14 +01:00
parent f6e39df157
commit b39ea7a647
3 changed files with 18 additions and 7 deletions
+12 -5
View File
@@ -174,7 +174,8 @@
const resp = await _origFetch("/api/lm-extra/fetch-stats", { method: "POST" });
const data = await resp.json();
if (data.success) {
btn.innerHTML = `<i class="fas fa-check"></i> <span>${data.updated} updated</span>`;
const count = parseInt(data.updated, 10) || 0;
btn.innerHTML = `<i class="fas fa-check"></i> <span>${count} updated</span>`;
setTimeout(() => {
btn.innerHTML = '<i class="fas fa-chart-bar"></i> <span>Fetch Stats</span>';
btn.disabled = false;
@@ -205,13 +206,19 @@
addFetchStatsButton();
patchCards();
let debounceTimer = null;
const observer = new MutationObserver(() => {
patchCards();
patchSortDropdown();
addFetchStatsButton();
if (debounceTimer) return;
debounceTimer = setTimeout(() => {
debounceTimer = null;
patchCards();
patchSortDropdown();
addFetchStatsButton();
}, 200);
});
observer.observe(document.body, { childList: true, subtree: true });
const grid = document.getElementById("modelGrid");
observer.observe(grid || document.body, { childList: true, subtree: true });
}
// ── Init ───────────────────────────────────────────────────────