Sandboxed webpage in SvelteKit causes SOP error

53 Views Asked by At

I have a SvelteKit website where users can upload JS code that other users then can run in their web browsers. To make it secure, the webpage running the user provided JS code has a Content-Security Policy that limits what the JS code may do, and I've almost got this to work.

My problem is that I want to use the sandbox directive without the allow-same-origin value, because I don't want the user provided JS code to be able to read/change the data other users have in their localStorage on my website. But when I remove that value, the webpage gets its own unique/null origin, and that gives me a Same-Origin Policy error that looks like this for each JS file the webpage tries to fetch:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://my-website.com/_app/immutable/entry/start.8e96ba46.js. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.

Now I'm stuck.

  1. Is there a way to add CORS headers to the responses for these static files in SvelteKit?
  2. Is it possible to somehow "inline" the requested JS files on this specific webpage that is sent back, so the web browser doesn't need to send the HTTP requests for the JS files at all?
  3. Is there another way to achieve what I want?

The code causing the cross-domain requests is the standard SvelteKit code on the page:

<script>
    {
        __sveltekit_i1n7th = {
            base: new URL("../..", location).pathname.slice(0, -1),
            env: {}
        };

        const element = document.currentScript.parentElement;

        const data = [null,null];

        // These trigger other imports in turn.
        Promise.all([
            import("../../_app/immutable/entry/start.ec215fac.js"),
            import("../../_app/immutable/entry/app.4c6d3256.js")
        ]).then(([kit, app]) => {
            kit.start(app, element, {
                node_ids: [0, 16],
                data,
                form: null,
                error: null
            });
        });
    }
</script>

Related reading:

  • The "official" SvelteKit solution for now seems to be to add a proxy server (source)
1

There are 1 best solutions below

0
Peppe L-G On

It's not pretty, but setting up my own custom server/proxy and adding the CORS header there solved it for me:

server.js

import { handler } from '../build/handler.js'
import http from 'node:http'

const server = http.createServer(function(request, response){
    
    if(request.url?.startsWith(`/_app/immutable/`)){
        response.setHeader(
            `Access-Control-Allow-Origin`,
            `*`,
        )
    }
    
    // Not sure if I'm using handler() correct like this,
    // but it seems to work for me.
    handler(request, response)
    
})

server.listen(3000)

Feels like one shouldn't need to do something this complicated to do something as easy as adding headers to a response though.