Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harden exposed endpoints #620

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Conversation

jrvidal
Copy link

@jrvidal jrvidal commented Feb 22, 2023

👋 Hi there! At Stackblitz we rely heavily on Comlink (as you might already be aware), and we're big fans, thanks for you work!

Recently, we've encountered a situation where one of our Comlink endpoints is not fully under our control (see @webcontainer/api). In this scenario, we would welcome some extra assurance that what we expose is exactly what we intend to, and nothing else. You could argue that Comlink, being about seamless RPC, might not 100% be the best fit for it, but we went ahead anyway because of its ergonomics 😅

This patch is more or less what we've added to a internal fork for the purposes of "hardening" Comlink.expose(). It is somewhat nice b/c it only affects the "server" side endpoint, while the "client" endpoint does not need any new codepath.

I am not fully convinced this belongs in Comlink proper, but we wanted to show it to you anyway. We are actually considering moving this "hardening" to a external Proxy that wraps our exposed objects. One disadvantage of doing that is that, AFAICS, when Comlink traverses a path for a exposed object, we would need to create proxies on the fly.

⚠️ This patch is adapted from something we built on top of Comlink 4.3.0, so it is not as thouroughly tested as it should be.


This adds ExposeOptions to Comlink.expose(). options.spec allows you to specify a "spec" of the object being exposed, a description of what the other side of the endpoint can do with the object. For instance, with the following spec:

Comlink.expose(obj, ep, {
  spec: {
    walk: "function",
    bar: { jump: "function", name: "primitive" }
  }
});

the other side of the endpoint cannot perform certain actions:

const obj = Comlink.wrap(ep);

// Allowed
obj.walk();
obj.bar.jump();
console.log(await obj.bar.name);

// Not allowed
obj.walk.toString();
obj.bar.jump.foo = 1;
await obj.bar.name.__proto__;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant