mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +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:
@@ -6,7 +6,7 @@
|
||||
import browser from "webextension-polyfill";
|
||||
|
||||
import { standalone as StandaloneStore } from "../utils/standalone.svelte";
|
||||
import { onMount } from "svelte";
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
|
||||
import { closeExtensionPopup } from "@/seqta/utils/Closers/closeExtensionPopup";
|
||||
@@ -108,12 +108,14 @@
|
||||
showDisclaimerModal = true;
|
||||
};
|
||||
|
||||
const closePopupsOnSettingsClose = () => {
|
||||
showColourPicker = false;
|
||||
showFontPicker = false;
|
||||
showCloudPanel = false;
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
settingsPopup.addListener(() => {
|
||||
showColourPicker = false;
|
||||
showFontPicker = false;
|
||||
showCloudPanel = false;
|
||||
});
|
||||
settingsPopup.addListener(closePopupsOnSettingsClose);
|
||||
|
||||
if (standalone) {
|
||||
StandaloneStore.setStandalone(true);
|
||||
@@ -125,6 +127,10 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
settingsPopup.removeListener(closePopupsOnSettingsClose);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import { closeExtensionPopup } from "@/seqta/utils/Closers/closeExtensionPopup"
|
||||
import { getSnapshotForUpload } from "@/seqta/utils/cloudSettingsSync"
|
||||
import { getStoredOverride, setApiBase } from "@/seqta/utils/DevApiBase"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
let devApiBaseInput = $state<string>(getStoredOverride() ?? "")
|
||||
let devApiBaseActive = $state<string | null>(getStoredOverride())
|
||||
@@ -128,9 +129,9 @@
|
||||
await browser.storage.local.set({ [storageKey]: currentSettings });
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
loadPluginSettings();
|
||||
})
|
||||
onMount(() => {
|
||||
void loadPluginSettings();
|
||||
});
|
||||
|
||||
const { showColourPicker, showFontPicker, showDisclaimer, showCloudPanel } = $props<{
|
||||
showColourPicker: () => void;
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
const themeManager = ThemeManager.getInstance();
|
||||
let cloudLoggedIn = $state(cloudAuth.state.isLoggedIn);
|
||||
|
||||
cloudAuth.subscribe((s) => { cloudLoggedIn = s.isLoggedIn; });
|
||||
$effect(() => {
|
||||
const unsub = cloudAuth.subscribe((s) => { cloudLoggedIn = s.isLoggedIn; });
|
||||
return unsub;
|
||||
});
|
||||
|
||||
// State variables
|
||||
let searchTerm = $state('');
|
||||
@@ -86,13 +89,11 @@
|
||||
}
|
||||
|
||||
const toggleFavorite = async (theme: Theme) => {
|
||||
const token = await cloudAuth.getStoredToken();
|
||||
if (!token) return;
|
||||
if (!cloudLoggedIn) return;
|
||||
const isFavorite = !theme.is_favorited;
|
||||
const result = (await browser.runtime.sendMessage({
|
||||
type: 'cloudFavorite',
|
||||
themeId: theme.id,
|
||||
token,
|
||||
action: isFavorite ? 'favorite' : 'unfavorite',
|
||||
})) as { success?: boolean };
|
||||
if (result?.success) {
|
||||
@@ -119,14 +120,12 @@
|
||||
error = null;
|
||||
}
|
||||
try {
|
||||
const token = await cloudAuth.getStoredToken();
|
||||
const data = await sendMessageWithTimeout<{
|
||||
success?: boolean;
|
||||
data?: { themes: unknown[] };
|
||||
error?: string;
|
||||
}>({
|
||||
type: 'fetchThemes',
|
||||
token: token ?? undefined,
|
||||
});
|
||||
if (!data?.success || !Array.isArray(data?.data?.themes)) {
|
||||
throw new Error(data?.error || 'Failed to fetch themes');
|
||||
|
||||
Reference in New Issue
Block a user