🔒 Fix CSP vulnerability by removing unsafe-inline for styles

Removes the 'unsafe-inline' directive from the style-src Content
Security Policy to prevent potential Cross-Site Scripting (XSS)
or malicious style injections. Replaces inline style manipulations
(`style.display = "none"`, `style=""`) with class list toggling
using a new `.d-none` utility class.

Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] 2026-08-12 18:13:03 +00:00
parent 268ac9e81b
commit 3ada5cf858
4 changed files with 9 additions and 8 deletions

View file

@ -30,7 +30,7 @@
</div>
<div id="statusbar">
<span id="rates-info" title=""></span>
<span id="market-info" title="" style="display:none"></span>
<span id="market-info" title="" class="d-none"></span>
<span class="spacer"></span>
<div id="export-wrap">
<button id="export-btn" title="Export" aria-label="Export">⤓</button>

View file

@ -23,7 +23,7 @@
}
],
"security": {
"csp": "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src ipc: http://ipc.localhost https://open.er-api.com https://api.coingecko.com https://query1.finance.yahoo.com https://query2.finance.yahoo.com https://api.frankfurter.dev"
"csp": "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self'; img-src 'self' data:; font-src 'self' data:; connect-src ipc: http://ipc.localhost https://open.er-api.com https://api.coingecko.com https://query1.finance.yahoo.com https://query2.finance.yahoo.com https://api.frankfurter.dev"
}
},
"bundle": {

View file

@ -596,7 +596,7 @@ function applyAllRates(): void {
async function refreshMarket(force = false): Promise<void> {
if (!isTauri()) return;
const info = $("#market-info") as HTMLElement;
info.style.display = "";
info.classList.remove("d-none");
info.classList.add("spin");
info.textContent = t("market");
const prices = await fetchMarketData(MARKET_SYMBOLS);
@ -636,8 +636,8 @@ async function fetchNeededHistoricalRates(text: string): Promise<void> {
function renderMarketInfo(): void {
const el = $("#market-info") as HTMLElement;
if (marketFetchedAt === 0) { el.style.display = "none"; return; }
el.style.display = "";
if (marketFetchedAt === 0) { el.classList.add("d-none"); return; }
el.classList.remove("d-none");
el.textContent = `${t("market")}: ${agoText(marketFetchedAt)} ↺`;
el.title = t("refreshRates");
}
@ -661,9 +661,9 @@ function renderTotal(): void {
lbl.textContent = label;
line.append(lbl, document.createTextNode(total));
line.dataset.value = total;
line.style.display = "";
line.classList.remove("d-none");
} else {
line.style.display = "none";
line.classList.add("d-none");
delete line.dataset.value;
}
}
@ -872,7 +872,7 @@ async function bindWindowControls(): Promise<void> {
$("#win-min").addEventListener("click", () => void win.minimize());
$("#win-close").addEventListener("click", () => void win.hide());
} else {
$("#win-controls").style.display = "none";
$("#win-controls").classList.add("d-none");
}
}

View file

@ -654,3 +654,4 @@ body {
}
.cm-tooltip-autocomplete ul li { font-family: var(--mono); font-size: 13px; color: var(--fg); }
.cm-tooltip-autocomplete ul li[aria-selected] { background: var(--sel); color: var(--fg); }
.d-none { display: none !important; }