mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-17 17:07:07 +00:00
fix: harden extension security and plugin reliability
Address audit findings across background handlers, openers, plugins, and UI: URL allowlists, XSS reductions, popup lifecycle fixes, plugin dispose/cleanup, cloud sync hardening, global search mathjs sandbox, and settings storage fixes.
This commit is contained in:
@@ -255,9 +255,9 @@ const watchNavigator = (navigator: Element, onChange: () => void) => {
|
||||
return observer;
|
||||
};
|
||||
|
||||
const handleSlidePane = (pane: Element) => {
|
||||
const handleSlidePane = (pane: Element): (() => void) => {
|
||||
const navigator = pane.querySelector(".navigator");
|
||||
if (!navigator) return;
|
||||
if (!navigator) return () => {};
|
||||
|
||||
requestAnimationFrame(() => scrollSelectedIntoView(navigator));
|
||||
setTimeout(() => scrollSelectedIntoView(navigator), 50);
|
||||
@@ -272,17 +272,22 @@ const handleSlidePane = (pane: Element) => {
|
||||
childList: true,
|
||||
});
|
||||
|
||||
const cleanup = new MutationObserver((muts) => {
|
||||
const paneCleanup = new MutationObserver((muts) => {
|
||||
muts.forEach((m) => {
|
||||
m.removedNodes.forEach((n) => {
|
||||
if (n === pane) {
|
||||
observer.disconnect();
|
||||
cleanup.disconnect();
|
||||
paneCleanup.disconnect();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
cleanup.observe(document.body, { childList: true });
|
||||
paneCleanup.observe(document.body, { childList: true });
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
paneCleanup.disconnect();
|
||||
};
|
||||
};
|
||||
|
||||
const enhancedNavigationPlugin: Plugin<typeof settings> = {
|
||||
@@ -301,7 +306,11 @@ const enhancedNavigationPlugin: Plugin<typeof settings> = {
|
||||
window.addEventListener("resize", positionArrows);
|
||||
window.addEventListener("scroll", positionArrows, true);
|
||||
|
||||
api.seqta.onMount(".course", async (element) => {
|
||||
const navObservers: MutationObserver[] = [];
|
||||
const courseObservers: MutationObserver[] = [];
|
||||
const slidePaneCleanups: Array<() => void> = [];
|
||||
|
||||
const courseMount = api.seqta.onMount(".course", async (element) => {
|
||||
const course = element as HTMLElement;
|
||||
let navObserver: MutationObserver | null = null;
|
||||
|
||||
@@ -318,6 +327,7 @@ const enhancedNavigationPlugin: Plugin<typeof settings> = {
|
||||
}
|
||||
ensureArrows(course);
|
||||
});
|
||||
navObservers.push(navObserver);
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -325,6 +335,7 @@ const enhancedNavigationPlugin: Plugin<typeof settings> = {
|
||||
const courseObserver = new MutationObserver(() => {
|
||||
if (setup()) courseObserver.disconnect();
|
||||
});
|
||||
courseObservers.push(courseObserver);
|
||||
courseObserver.observe(course, { childList: true, subtree: true });
|
||||
}
|
||||
});
|
||||
@@ -334,13 +345,21 @@ const enhancedNavigationPlugin: Plugin<typeof settings> = {
|
||||
m.addedNodes.forEach((n) => {
|
||||
if (n.nodeType !== 1) return;
|
||||
const el = n as Element;
|
||||
if (el.classList?.contains("uiSlidePane")) handleSlidePane(el);
|
||||
if (el.classList?.contains("uiSlidePane")) {
|
||||
slidePaneCleanups.push(handleSlidePane(el));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
bodyObserver.observe(document.body, { childList: true });
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", positionArrows);
|
||||
window.removeEventListener("scroll", positionArrows, true);
|
||||
courseMount.unregister();
|
||||
navObservers.forEach((observer) => observer.disconnect());
|
||||
courseObservers.forEach((observer) => observer.disconnect());
|
||||
slidePaneCleanups.forEach((cleanup) => cleanup());
|
||||
bodyObserver.disconnect();
|
||||
document.getElementById(ARROW_CONTAINER_ID)?.remove();
|
||||
document.getElementById(STYLE_ID)?.remove();
|
||||
|
||||
Reference in New Issue
Block a user