2

I run a small blogging platform, and I want my users to be able to embed javascript that runs on their blogs (to manipulate the DOM, etc. as you might if you were hosting your own website). However, I do not want them to be able to:

The way I see it, all of the above vulnerabilities would be solved if their injected code simply couldn't make any HTTP requests (or if I could block all but a certain subset).

Can I use a ServiceWorker to reliably intercept and block all but a whitelisted subset of outgoing HTTP requests?

Is there a better way?

1 Answer 1

3

No, of course not. You cannot use service workers to prevent some javascript code from making HTTP requests. The malicious code could simply deregister your service worker.
Or it could register its own SW with a more specific scope (and different behavior).

You can use the connect-src and the form-action features of CSP. You can isolate the script with an iframe with a sandbox attribute, served from a different origin (a subdomain will do unless you explicitly relaxed this) and with proper CSP headers.
If you serve the user-generated content in an iframe from a different origin it won't be able to access the cookies, the Storage, or any element outside of the user-generated page.
This way an attacker can only steal from themself.

The best approach however is to have a separate blog administration origin (read: subdomain) that is completely agnostic to and (automatically) unaccessible from the user-generated content.
Pretty much like wordpress.com or similars do it.

Regarding your points: the first one is already taken care of by the browser. See Same Origin Policy.
To isolate scripts use different origins (as explained above, an iframe create an "anonymous" origin).

The last two points are already doable with a form and as soon as your blogging features forms or similar data-collecting mechanisms, people will use it for phishing if it's convenient enough.
This is a human problem, not a technical one. People get phished/scammed even with simple static pages, let alone with JS-enabled pages, where detecting phishing is most likely undecidable (it's easy to add an obfuscated script that will render the DOM at page-load time).
So the best approach remains a competent, responsive, and fast abuse service (present at least on Twitter, where most researchers are).
FWIW, phishing is being hosted daily on every major blogging/hosting platform.

Finally, if your users should have more restrictions than freedom consider giving them something less powerful than JS.
For example a less expressive, ad hoc, language. This can be technically difficult to implement if the required skills are missing and may backfire if done without the due care but it's doable (for example you can allow only a small set of whitelisted elements with a small set of whitelisted attributes, a small set of actions and use CSP to have the transpiled script as the single allowed source).

2
  • Thank you! This is a really excellent and helpful answer. I submitted one edit to remove the bit about service worker scope limitations. Service worker scope limits which origins + paths a service worker runs in. It does not limit which URLs it can intercept.
    – bennlich
    Dec 31, 2022 at 12:37
  • Based on your answer, I feel like the best solution is a combination of CSP connect-src + form-action (to prevent phishing) AND separating the admin origin (to prevent authing to the blog admin API with the user's cookie). Does that sound right to you?
    – bennlich
    Dec 31, 2022 at 12:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.