tracker: allow unsafe-eval, which the SID engine cannot run without - #212
Merged
Conversation
SIDs failed on the deployed Pi with "Couldn't play this module" and a CSP violation, while modules played fine. libsidplayfp is bound through Emscripten's Embind, which builds its invoker functions with the `Function` constructor — string evaluation, which `'wasm-unsafe-eval'` does not cover; that permits wasm compilation and nothing else. libopenmpt reaches its C API through `cwrap` and needs none of it, hence one format working and the other not. Neither shipped artifact avoids it — residfp and sidlite both use Embind — and a worker cannot relax an inherited policy, since a dedicated worker's CSP is the union of its own and its owner's. So it is this or no SID playback. Narrowing it again means rebuilding the wasm with `-sDYNAMIC_EXECUTION=0`, which is upstream work. Everything else stays as strict as it was: no `'unsafe-inline'` for scripts, the SvelteKit bootstrap still hashed, connect-src / img-src / frame-ancestors untouched. Worth recording why no test caught this: the CSP is set by *this* backend, and the e2e suite serves the built SPA through `vite preview`, which sends no CSP at all. So the whole suite passes against a page whose security policy bears no resemblance to production. Reproduced by running the real backend over the real build and driving it with a browser — the violation named the directive but not the cause, and the stack was the only thing that pointed at Embind (the minified call is `Function(...)`, not `new Function`, so grepping for the obvious spelling found nothing). The unit test now pins `'unsafe-eval'` with that reasoning attached, because it reads exactly like something a future tightening pass should remove — and removing it breaks SID playback silently as far as CI is concerned.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SIDs fail on tracker.anarkisti.com with
Couldn't play this moduleand a CSPviolation, while working on the dev server. Modules play fine either way.
libsidplayfp is bound through Emscripten's Embind, which builds its invoker
functions with the
Functionconstructor — string evaluation, which'wasm-unsafe-eval'does not cover (that permits wasm compilation andnothing else). libopenmpt reaches its C API through
cwrapand needs none ofit, which is exactly why one format worked and the other didn't.
Neither shipped artifact avoids it — residfp and sidlite both use Embind — and a
worker can't relax an inherited policy, since a dedicated worker's CSP is the
union of its own and its owner's. So it's
'unsafe-eval'or no SID playback.Narrowing it again means rebuilding the wasm with
-sDYNAMIC_EXECUTION=0, whichis upstream work.
Everything else stays as strict as it was: no
'unsafe-inline'for scripts, theSvelteKit bootstrap still hashed,
connect-src/img-src/frame-ancestorsuntouched.
Why nothing caught it
The CSP is set by the Rust backend, and it's the only thing that sets one. The
dev server sends none, and the e2e suite runs the built SPA through
vite preview— which also sends none. So the whole suite passes against a pagewhose security policy bears no resemblance to production.
That's the third escape of this shape on this feature: a dev-only
fs.allow403, a worker no typecheck covered, and now this. A spec that runs the real
backend over the real build would have caught all three; I reproduced this one
that way and it's worth making permanent, but it's a new harness rather than
something to bolt onto a one-line fix.
The unit test pins
'unsafe-eval'with the reasoning attached, because itreads exactly like something a future tightening pass should delete — and
deleting it breaks SID playback in a way CI cannot see.
Verification
Reproduced against the real backend serving the real build, then confirmed
fixed: transport 0:05, no error banner, no CSP violations. Before the fix,
same setup, same page:
EvalError … 'unsafe-eval' is not an allowed source.The stack was the only thing that identified Embind — the minified call is
Function(...), notnew Function, so grepping for the obvious spelling foundnothing and sent me looking in the wrong place first.
79 backend unit · 35 integration · clippy 0 warnings · fmt clean.
(Split out of #211, which merged before this commit landed on the branch.)