Files
Tha.Les d159429c59 feat: add Content-Security-Policy to the webview (#171) (#177)
The desktop webview ran with csp:null while withGlobalTauri exposed the
Tauri API, so any markup injection could reach Tauri commands. Add a strict
CSP as defense-in-depth:

- FastAPI sends a CSP response header (the main app — where the library/
  folder UI and the window.__TAURI__ surface live — is served by FastAPI at
  127.0.0.1, so the header is the effective policy there). script-src 'self'
  with no unsafe-inline/eval.
- Move the inline <script> + 3 inline onclick handlers out of index.html into
  a new static/js/ui-chrome.js module so the strict policy doesn't break them.
- Set a matching CSP for the bundled Tauri setup shell in tauri.conf.json.

Styles keep 'unsafe-inline' (the UI sets many style attributes); connect-src
allows same-origin API/SSE, the GitHub update check, and Tauri ipc:; img-src
allows https: for remote thumbnails. withGlobalTauri kept (disabling it is a
larger refactor for marginal gain once the XSS in #170 is fixed + CSP is on).
2026-06-03 07:12:59 +01:00

32 lines
1.1 KiB
JavaScript

// Small UI-chrome handlers extracted from inline index.html scripts / onclick
// attributes so the Content-Security-Policy can forbid inline script (#171).
// Loaded as a module (deferred), so the DOM is parsed before this runs.
// Upload button → trigger the hidden file input.
document.getElementById("uploadFileBtn")?.addEventListener("click", () => {
document.getElementById("fileInput")?.click();
});
// Notification panel: toggle / close / close-on-outside-click.
const notifBtn = document.getElementById("notifBtn");
const notifWrap = notifBtn?.closest(".daw-notif-wrap");
function setNotifOpen(open) {
notifWrap?.classList.toggle("open", open);
notifBtn?.setAttribute("aria-expanded", String(open));
}
notifBtn?.addEventListener("click", () => {
setNotifOpen(!notifWrap?.classList.contains("open"));
});
document
.querySelector(".daw-notif-close")
?.addEventListener("click", () => setNotifOpen(false));
document.addEventListener("click", (e) => {
if (notifWrap?.classList.contains("open") && !notifWrap.contains(e.target)) {
setNotifOpen(false);
}
});