Slide 1

Slide 1 text

Running untrusted code in Node in a safe mode while handling the lode

Slide 2

Slide 2 text

lode?

Slide 3

Slide 3 text

Dave Wasmer @davewasmer Developer @ Kinvey yep, this slide …

Slide 4

Slide 4 text

Kinvey Backend as a service … and this one.

Slide 5

Slide 5 text

What goes into backend as a service?

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Lots o’ stuff • Data storage • User management • Twitter, Facebook, G+, LinkedIn • OAuth, LDAP, Active Directory • File storage • don’t forget CDN delivery • Push notifications • Emails • 3rd Party API Integration • Analytics • a whole lot more ..

Slide 8

Slide 8 text

What if CRUD ain’t enough?

Slide 9

Slide 9 text

enter: Business Logic!

Slide 10

Slide 10 text

Run your code on our servers

Slide 11

Slide 11 text

Custom JavaScript execution?!

Slide 12

Slide 12 text

eval(customerCode); // Genius, mirite? NO!

Slide 13

Slide 13 text

The Problem We needed a safe, scalable way to run arbitrary (possibly malicious) JavaScript on our servers.

Slide 14

Slide 14 text

Safety • Can’t allow access to: • filesystem • shared memory • Kinvey internals • State is evil!

Slide 15

Slide 15 text

Scalablity • Needs to scale horizontally • i.e. spin up new instances on-demand • automatically add to resource pool • Optimize for usage • not running huge computations - short, frequent bursts of activity • 2x per API request is possible!

Slide 16

Slide 16 text

Our solution to scalability KCS KCS KCS KBL KBL KBL Redis Work Master Child Child Child Child

Slide 17

Slide 17 text

Our solution to scalability KCS KCS KCS KBL KBL KBL Redis Work Master Child Child Child Child

Slide 18

Slide 18 text

Our solution to scalability KCS KCS KCS KBL KBL KBL Redis Work Master Child Child Child Child

Slide 19

Slide 19 text

Our solution to scalability KCS KCS KCS KBL KBL KBL Redis Work Master Child Child Child Child

Slide 20

Slide 20 text

Our solution to scalability Work Master Child Child Child Child

Slide 21

Slide 21 text

Safety Concerns • How to run arbitrary JS code? • Three issues • System access (filesystem, network, etc) • Application access (application state, data, etc) • Stupidity / DoS (while (true), forgot to signal async completed)

Slide 22

Slide 22 text

System access • Filesystem • Severely limited or none • Network • Partially limited

Slide 23

Slide 23 text

Our solution to system access ! // Setting things up ! try { script = vm.createScript(codeAsStr); } catch (e) { // syntax error! } ! sandbox = generateNewSandbox()

Slide 24

Slide 24 text

generateNewSandbox = function(){ ! var sandbox = {}; sandbox.complete = function(){ runNextTask(); }; sandbox.whateverYouWant = function(){ ... } return sandbox; ! } Our solution to system access

Slide 25

Slide 25 text

! // Running the untrusted script try { script.runInNewContext(sandbox) } catch (e) { // e will be any immediate (synchronous) // runtime errors } Our solution to system access

Slide 26

Slide 26 text

Application access • Data • Permissions

Slide 27

Slide 27 text

Our solution to application access ! // inside generateNewSandbox() ! sandbox.db = { find: function(query, callback) { // do db stuff callback(null, result) // <- Careful! }, ...
 }

Slide 28

Slide 28 text

Stupidity / DoS • while (true) {} // single-threaded ftw! • function onPreSave(req, res, modules) {
 doSomeAsyncStuff()
 } // kthxbai • function doSomeAsyncStuff() {
 setTimeout(function(){ 
 throw new Error() 
 }, 100000); // muhahaha
 }

Slide 29

Slide 29 text

Our solution to stupidity / DoS Work Master Child Child Child Child

Slide 30

Slide 30 text

Our solution to stupidity / DoS Work Master Child Child Child Child

Slide 31

Slide 31 text

Our solution to stupidity / DoS ! // For handling callback errors process.on(‘uncaughtException’, function(){ // handle it here });

Slide 32

Slide 32 text

Wrap-up