Locking Javascript objects

Jan 28, 2015 at 3:51 PM

Basically I work on a platform in C# that distributes content. Sometimes that content has custom actions that the platform needs to support (Like installing things in specific places, or providing some extra functionality etc)

I had the idea of using the ClearScript Engine (or something similar) to allow content to provide scripts for our platform to carry out, rather than us hard coding support in for specific content and releasing platform updates.

The general idea is:
  • Platform (C#)
  • Protected Services (C#) (Provides IO operations etc...)
  • Content Services (TS->JS)
  • Content Scripts (TS->JS)
The Platform would load content scripts with the content and then hand off the required services to those scripts.

The problem I forsee is that when a content script gets hold of a service object it also has the ability to rewrite the functions in that script and carry out malicious actions. The same could be said if one Content Script gets a hold of another.

My current idea was to proxy JS objects through C# between engines on the same runtime so that the prototypes of the JS objects would remain protected. One issue with this though is that I'd have to proxy the function calls too since I'd also need to protect any object passed between the two JS objects, and so on. It becomes recursive.

I was wondering if there is an easy way to protect the prototypes of JS Objects between Engines. So inside one engine the object is manipulable but if it was passed to another engine it becomes protected so that functions can't be rewritten maliciously.

Jan 30, 2015 at 2:48 PM

In general we don't recommend passing script objects from one engine to another, even if those engines are in the same V8 runtime. ClearScript has some support for this, and even some unit tests, but it doesn't leverage V8's one-shared-heap-per-runtime architecture. That is, an engine may hold a foreign script object, but its access to that object will always be proxied through the managed ClearScript layer, and that involves a lot of overhead. Note that this doesn't apply to host objects, which you can expose in multiple engines without additional overhead.

As for securing your script platform against untrusted scripts, there are things you can do, especially if you're using V8. Some suggestions:
  1. Instead of executing untrusted scripts directly within the global context, consider wrapping them within anonymous functions that internally enable strict mode.
  2. Use Object.defineProperty() and Object.freeze() to harden your service objects.