a27762b518
* fix: allow data:/blob: in CSP connect-src so stems load (#186) The CSP from #171 omitted data:/blob: from connect-src. multitrack.js fetches a data: URI during track init, the browser blocked it, Multitrack.create threw, and no audio elements were created — blank lane waveforms, 0:00, no playback in every browser, for both YouTube and local jobs. Add data: blob: to connect-src. Both are inline/same-origin schemes (not network endpoints), already trusted in this policy for media-src/img-src/font-src, so no exfiltration channel opens. script-src 'self' (no unsafe-inline/eval — the actual XSS-execution defense from #171) is untouched. Adds tests/test_csp.py guarding both the data:/blob: allowance and that script-src stays locked. Diagnosis, patch, and regression test by @drewmerc302 (fork PRs are restricted, so applied on their behalf). Co-Authored-By: drewmerc302 <drewmerc302@users.noreply.github.com> * fix: show SVG overview waveform when the engine owns playback #185 mounts the multitrack with null URLs when the Web Audio engine is active, so WaveSurfer never decodes audio and its canvas — the normal visible waveform source — is empty. The SVG overview layer (rendered from peaks.json) is CSS-hidden by `.daw .stem-waveform-layer { display: none }`, so the studio showed no waveform at all whenever the engine was on (every platform; most visible in Safari/WebKit). Add an `engine-waveforms` class on `.app` while the engine owns playback and unhide the SVG layer in that state, so it becomes the visible waveform source. Verified end-to-end in Playwright WebKit (Safari engine) with a real track: waveforms render in every lane, playback advances, zero CSP violations. --------- Co-authored-by: drewmerc302 <drewmerc302@users.noreply.github.com>
31 lines
1.0 KiB
Python
31 lines
1.0 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.main import app
|
|
|
|
|
|
def _csp_directive(name: str) -> str:
|
|
"""Return the named directive from the served Content-Security-Policy header."""
|
|
with TestClient(app) as c:
|
|
resp = c.get("/")
|
|
csp = resp.headers["content-security-policy"]
|
|
return next(d.strip() for d in csp.split(";") if d.strip().startswith(name))
|
|
|
|
|
|
def test_connect_src_permits_data_and_blob():
|
|
# Regression for #186: multitrack.js fetches a data: URI while initializing
|
|
# each track's audio. Without data:/blob: in connect-src the browser blocks
|
|
# it, Multitrack.create throws, and no audio/waveform/playback loads.
|
|
connect = _csp_directive("connect-src")
|
|
assert "data:" in connect
|
|
assert "blob:" in connect
|
|
|
|
|
|
def test_script_src_stays_locked():
|
|
# Lock #171's intent: loosening connect-src must not weaken the XSS defense.
|
|
script = _csp_directive("script-src")
|
|
assert "'self'" in script
|
|
assert "unsafe-inline" not in script
|
|
assert "unsafe-eval" not in script
|