SlideShare a Scribd company logo
1 of 50
Download to read offline
Improving JavaScript (d)app security by practicing extreme modularity


A Practitioner’s guide to Hardened JavaScript
Tom Van Cutsem
@tvcutsem
About me
• Today: Computer scientist and research director at Nokia Bell Labs


• In a past life: TC39 member and active contributor to ECMAScript standards


• Author of standard Proxy and Re
fl
ect APIs (since ECMAScript 2015)


• Turning JS into a smart contracting language before Ethereum existed
@tvcutsem
tvcutsem.github.io
A software architecture view of app security
OAuth
certi
fi
cate pinning
cookies
same-origin policy
CSRF
content security policy
html sanitization
HSTS
A software architecture view of app security
OAuth
certi
fi
cate pinning
cookies
isolation
functions
encapsulation
data
fl
ow
dependencies
modules
immutability
same-origin policy
CSRF
content security policy
html sanitization
HSTS
A software architecture view of app security
“Security is just the extreme of Modularity”
- Mark S. Miller


(Chief Scientist, Agoric)
Modularity: avoid needless dependencies (to prevent bugs)


Security: avoid needless vulnerabilities (to prevent exploits)
It’s all about trust
It is exceedingly common to run code you don’t know/trust in a common
environment
Webpage
Browser env (e.g. Firefox)
Web server app
Server env (e.g. node)
Module Module Module Module
Requests Files
DOM Cookies
It’s all about trust
Even more critical in Web3 where code may access digital assets or wallets
Webpage
Browser env (e.g. Firefox)
Web server app
Server env (e.g. node)
Module Module Module Module
Requests Files
DOM Cookies
Smart contract dapp
Blockchain env
Module Module
Assets Wallets
What can happen when code goes rogue?
Webpage
Browser env (e.g. Firefox)
Web server app
Server env (e.g. node)
Module Module Module Module
Requests Files
DOM Cookies
Smart contract dapp
Blockchain env
Module Module
Assets Wallets
What can happen when code goes rogue?
Web server app
Server env (e.g. node)
Module Module
Requests Files
npm	install	event-stream
(source: theregister.co.uk)
Avoiding interference is the name of the game
• Shield important resources/APIs from modules that don’t need access

• Apply Principle of Least Authority (POLA) to application design
Webpage
Browser env (e.g. Firefox)
Web server app
Server env (e.g. node)
Module Module Module Module
Requests Files
DOM Cookies
Smart contract dapp
Blockchain env
Module Module
Tokens Keys
Running example: apply POLA to a basic shared log
We would like Alice to only write to the log, and Bob to only read from the log.
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = new Log()
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
Running example: apply POLA to a basic shared log
If Bob goes rogue, what could go wrong?
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = new Log()
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
Bob has way too much authority!
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = new Log()
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can replace the Array built-in
s

Array.prototype.push = function(msg)
{

console.log(“I’m not logging anything”)
;

}
Load each module in its own environment,

with its own set of “primordial” objects
How to solve “prototype poisoning” attacks?
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = new Log()
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can replace the Array built-in
s

Array.prototype.push = function(msg)
{

console.log(“I’m not logging anything”)
;

}
Intuitions: “iframe without DOM”, “principled version of node’s `vm` module”
ShadowRealms (TC39 Stage 3 proposal)
ShadowRealm
Host environment
ShadowRealm
globalThis
Array
globalThis
Primordials*
Math
Objects
* Primordials: built-in objects like Object, Object.prototype, Array, Function, Math, JSON, etc.
Array
Math
Each Compartment has its own global object but shared (immutable) primordials.
Compartments (TC39 Stage 1 proposal)
Host environment
Compartment Compartment
Array
globalThis
Array
globalThis globalThis
Primordials*
Math
Objects
Deep-frozen


Primordials
Deep-frozen


Objects
Math
* Primordials: built-in objects like Object, Object.prototype, Array, Function, Math, JSON, etc.
ShadowRealm ShadowRealm
Hardened JavaScript
(inspired by the diagram at https://github.com/Agoric/Jessie )
• A subset of JavaScript,
building on Compartments


• Key idea: no powerful objects
by default. Code can only
affect the outside world only
through objects (capabilities)
explicitly granted to it (POLA)
import ‘ses’
;

lockdown();
Full ECMAScript (“WAT” JavaScript)
“use strict” (“sane” JavaScript)
Hardened JavaScript)
JSON (“data” JavaScript)
= strict-mode JavaScript


- mutable primordials


- ambient authority (powerful globals)


+ Compartments
LavaMoat
• Build tool that puts each of your app’s package
dependencies into its own sandbox

• Auto-generates con
fi
g
fi
le indicating authority
needed by each package

• Plugs into Webpack and Browserify
https://github.com/LavaMoat/lavamoat
Back to our example
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = new Log()
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can replace the Array built-in
s

Array.prototype.push = function(msg)
{

console.log(“I’m not logging anything”)
;

}
With Alice and Bob’s code running in their own

Compartment, we mitigate the poisoning attack
One down, three to go
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = new Log()
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}
Make the log’s interface tamper-proof
Object.freeze (ES5) makes property bindings
(not their values) immutable
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = Object.freeze(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}
Make the log’s interface tamper-proof. Oops.
Functions are mutable too. Freeze doesn’t
recursively freeze the object’s functions.
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = Object.freeze(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Make the log’s interface tamper-proof
Hardened JS provides a harden function
that “deep-freezes” an object
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = harden(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Two down, two to go
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = harden(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Two down, two to go
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return this.messages_;
}

}

let log = harden(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Don’t share access to mutable internals
• Modify read() to return a copy of the mutable state.

• Even better would be to use a more e
ffi
cient copy-on-write
or “persistent” data structure (see immutable-js.com )
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Three down, one to go
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Three down, one to go
• Recall: we would like Alice to only write to the log,
and Bob to only read from the log.

• Bob receives too much authority. How to limit?
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log)
;

bob(log);
JS app
Alice Bob
log
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;
Pass only the authority that Bob needs.
Just pass the write function to Alice and the
read function to Bob. Can you spot the bug?
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log.write)
;

bob(log.read);
JS app
Alice Bob
write
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;

read
𝑓𝑓
Pass only the authority that Bob needs.
To avoid, only ever pass bound functions
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log.write.bind(log))
;

bob(log.read.bind(log));
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;

JS app
Alice Bob
write read
𝑓𝑓
Success! We thwarted all of Evil Bob’s attacks.
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log.write.bind(log))
;

bob(log.read.bind(log));
// in bob.j
s

// Bob can just write to the lo
g

log.write(“I’m polluting the log”
)

// Bob can delete the entire lo
g

log.read().length = 0
// Bob can replace the ‘write’ functio
n

log.write = function(msg)
{

console.log(“I’m not logging anything”)
;

}

// Bob can still modify the write functio
n

log.write.apply = function() { “gotcha” }
;

JS app
Alice Bob
write read
𝑓𝑓
Is there a better way to write this code?
The burden of correct use is on the client of
the class. Can we avoid this?
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log.write.bind(log))
;

bob(log.read.bind(log));
JS app
Alice Bob
write read
𝑓𝑓
Use the Function as Object pattern
• A record of closures hiding state is a
fi
ne representation of an
object of methods hiding instance vars

• Pattern long advocated by Doug Crockford instead of using
classes or prototypes
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

class Log
{

constructor()
{

this.messages_ = []
;

}

write(msg) { this.messages_.push(msg);
}

read() { return [...this.messages_];
}

}

let log = harden(new Log())
;

alice(log.write.bind(log))
;

bob(log.read.bind(log));
JS app
Alice Bob
write read
𝑓𝑓
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

alice(log.write)
;

bob(log.read);
(See also https://martinfowler.com/bliki/FunctionAsObject.html )
Use the Function as Object pattern
JS app
Alice Bob
write read
𝑓𝑓
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

alice(log.write)
;

bob(log.read);
What if Alice and Bob need more authority?
JS app
Alice Bob
write read
𝑓𝑓
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

alice(log.write)
;

bob(log.read);
If over time we want to expose more functionality to
Alice and Bob, we need to refactor all of our code.
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

function size() { return messages.length();
}

return harden({read, write, size})
;

}

let log = makeLog()
;

alice(log.write, log.size)
;

bob(log.read, log.size);
size
𝑓
Expose distinct authorities through facets
Easily deconstruct the API of a single powerful
object into separate interfaces by nesting objects
JS app
Alice Bob
writer reader
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

function size() { return messages.length();
}

return harden(
{

reader: {read, size}
,

writer: {write, size}
})
;

}

let log = makeLog()
;

alice(log.writer)
;

bob(log.reader);
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

function size() { return messages.length();
}

return harden({read, write, size})
;

}

let log = makeLog()
;

alice(log.write, log.size)
;

bob(log.read, log.size);
Further limiting Bob’s authority
We would like to give Bob only temporary
read access to the log.
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

alice(log.write)
;

bob(log.read)
;

JS app
Alice Bob
write read
𝑓𝑓
Use caretaker to insert access control logic
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableLog(log)
;

alice(log.write)
;

bob(rlog.read)
;

JS app
Alice Bob
write
read
𝑓𝑓𝑓
We would like to give Bob only temporary
read access to the log.
Use caretaker to insert access control logic
We would like to give Bob only temporary
read access to the log.
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableLog(log)
;

alice(log.write)
;

bob(rlog.read)
;

// to revoke Bob’s access
:

revoke();
JS app
Alice Bob
write
read
𝑓𝑓𝑓
A caretaker is just a proxy object
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableLog(log)
;

alice(log.write)
;

bob(rlog.read)
;

JS app
Alice Bob
write
read
𝑓𝑓𝑓
function makeRevokableLog(log)
{

function revoke() { log = null; }
;

let proxy =
{

write(msg) { log.write(msg);
}

read() { return log.read();
}

}
;

return harden([proxy, revoke])
;

}
A caretaker is just a proxy object
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableLog(log)
;

alice(log.write)
;

bob(rlog.read)
;

// to revoke Bob’s access
:

revoke();
function makeRevokableLog(log)
{

function revoke() { log = null; }
;

let proxy =
{

write(msg) { log.write(msg);
}

read() { return log.read();
}

}
;

return harden([proxy, revoke])
;

}

JS app
Alice Bob
write
read
𝑓𝑓𝑓
Membranes are generalized caretakers
Proxy any object reachable from the log
JS app
Alice Bob
write
read
𝑓𝑓𝑓
msgs
[]
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableMembrane(log)
;

alice(log.write)
;

bob(rlog.read)
;

let msgs = read()
[]
Membranes are generalized caretakers
JS app
Alice Bob
write
read
𝑓𝑓
msgs
[]
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableMembrane(log)
;

alice(log.write)
;

bob(rlog.read)
;

// to revoke Bob’s access
:

revoke();
let msgs = read()
[]
𝑓
Membranes are generalized caretakers
JS app
Alice Bob
write
read
𝑓𝑓
msgs
[]
import * as alice from "alice.js"
;

import * as bob from “bob.js"
;

function makeLog()
{

const messages = []
;

function write(msg) { messages.push(msg);
}

function read() { return [...messages];
}

return harden({read, write})
;

}

let log = makeLog()
;

let [rlog, revoke] = makeRevokableMembrane(log)
;

alice(log.write)
;

bob(rlog.read)
;

// to revoke Bob’s access
:

revoke();
let msgs = read()
[]
𝑓
Deep dive at tvcutsem.github.io/membranes
Taming is the process of restricting access to powerful APIs
• Expose powerful objects through restrictive proxies to third-party code

• For example, Alice might give Bob read-only access to a speci
fi
c
subdirectory of her
fi
le system
JS app
Alice Bob
restricted


API	access
Host resources
full	API


access
These patterns are used in industry
Uses taming for safe html


embedding of third-party content
Mozilla Firefox Salesforce Lightning


Moddable XS
Uses membranes to isolate


site origins from privileged JS code
Google Caja
Uses realms and membranes to


isolate & observe UI components
Uses Compartments for safe end-user


scripting of IoT products
Uses Hardened JS for writing


smart contracts and Dapps
Uses LavaMoat to sandbox plugins


in their crypto web wallet
MetaMask Snaps Agoric Zoe
Talk summary
• Think of “app security” as practicing “extreme
modularity”

• Modern JS apps are composed from many
modules. You can’t trust them all.

• Apply the “principle of least authority” to limit trust. 

• Isolate modules using Hardened JS & Lavamoat

• Let modules interact safely using patterns such
as facets, caretaker, membranes, taming, …

• Understanding these patterns is critical in Web3
where code may have direct access to digital assets
JS app
Environment
Module Module
Shared resources
Tom Van Cutsem
@tvcutsem
Thanks for listening!
Improving JavaScript (d)app security by practicing extreme modularity


A Practitioner’s guide to Hardened JavaScript
Acknowledgements
• Mark S. Miller (for the inspiring and ground-breaking work on Object-capabilities, Robust Composition, E, Caja,
JavaScript and Secure ECMAScript)

• Marc Stiegler’s “PictureBook of secure cooperation” (2004) was a great source of inspiration for this talk

• Doug Crockford’s Good Parts and How JS Works books were an eye-opener and provide a highly opinionated take on
how to write clean, good, robust JavaScript code

• Kate Sills and Kris Kowal at Agoric for helpful comments on earlier versions of this talk

• The Cap-talk and Friam community for inspiration on capability-security and capability-secure design patterns

• TC39 and the es-discuss community, for the interactions during the design of ECMAScript 2015, and in particular all the
feedback on the Proxy API

• The SES secure coding guide: https://github.com/endojs/endo/blob/master/packages/ses/docs/secure-coding-
guide.md
Further Reading
• Compartments: https://github.com/tc39/proposal-compartments and https://github.com/Agoric/ses-shim


• ShadowRealms: https://github.com/tc39/proposal-realms and github.com/Agoric/realms-shim


• Hardened JS (SES): https://github.com/tc39/proposal-ses and https://github.com/endojs/endo/tree/master/packages/ses


• Subsetting ECMAScript: https://github.com/Agoric/Jessie


• Kris Kowal (Agoric): “Hardened JavaScript” https://www.youtube.com/watch?v=RoodZSIL-DE


• Making Javascript Safe and Secure: Talks by Mark S. Miller (Agoric), Peter Hoddie (Moddable), and Dan Finlay (MetaMask):
https://www.youtube.com/playlist?list=PLzDw4TTug5O25J5M3fwErKImrjOrqGikj


• Moddable: XS: Secure, Private JavaScript for Embedded IoT: https://blog.moddable.com/blog/secureprivate/


• Membranes in JavaScript: tvcutsem.github.io/js-membranes and tvcutsem.github.io/membranes


• Caja: https://developers.google.com/caja

More Related Content

What's hot

Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Anton Arhipov
 
Economies of Scaling Software
Economies of Scaling SoftwareEconomies of Scaling Software
Economies of Scaling SoftwareJoshua Long
 
The things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaThe things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaKonrad Malawski
 
The Theory Of The Dom
The Theory Of The DomThe Theory Of The Dom
The Theory Of The Domkaven yan
 
A Taste of Clojure
A Taste of ClojureA Taste of Clojure
A Taste of ClojureDavid Leung
 
Java Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To MissJava Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To MissAndres Almiray
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaKazuhiro Sera
 
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Anton Arhipov
 
The Naked Bundle - Symfony Usergroup Belgium
The Naked Bundle - Symfony Usergroup BelgiumThe Naked Bundle - Symfony Usergroup Belgium
The Naked Bundle - Symfony Usergroup BelgiumMatthias Noback
 
JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011Charles Nutter
 
Why Doesn't Java Has Instant Turnaround - Con-FESS 2012
Why Doesn't Java Has Instant Turnaround - Con-FESS 2012Why Doesn't Java Has Instant Turnaround - Con-FESS 2012
Why Doesn't Java Has Instant Turnaround - Con-FESS 2012Anton Arhipov
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Yevgeniy Brikman
 
From Ruby to Scala
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scalatod esking
 
Have You Seen Spring Lately?
Have You Seen Spring Lately?Have You Seen Spring Lately?
Have You Seen Spring Lately?Joshua Long
 
Deep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explainedDeep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explainedHolger Schill
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder RubyNick Sieger
 
Apache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentationApache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentationClaus Ibsen
 

What's hot (20)

Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012
 
Economies of Scaling Software
Economies of Scaling SoftwareEconomies of Scaling Software
Economies of Scaling Software
 
The things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaThe things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and Akka
 
CoffeeScript By Example
CoffeeScript By ExampleCoffeeScript By Example
CoffeeScript By Example
 
The Theory Of The Dom
The Theory Of The DomThe Theory Of The Dom
The Theory Of The Dom
 
A Taste of Clojure
A Taste of ClojureA Taste of Clojure
A Taste of Clojure
 
Java Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To MissJava Libraries You Can't Afford To Miss
Java Libraries You Can't Afford To Miss
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
 
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012
 
The Naked Bundle - Symfony Usergroup Belgium
The Naked Bundle - Symfony Usergroup BelgiumThe Naked Bundle - Symfony Usergroup Belgium
The Naked Bundle - Symfony Usergroup Belgium
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 
JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011
 
Why Doesn't Java Has Instant Turnaround - Con-FESS 2012
Why Doesn't Java Has Instant Turnaround - Con-FESS 2012Why Doesn't Java Has Instant Turnaround - Con-FESS 2012
Why Doesn't Java Has Instant Turnaround - Con-FESS 2012
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
From Ruby to Scala
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scala
 
Have You Seen Spring Lately?
Have You Seen Spring Lately?Have You Seen Spring Lately?
Have You Seen Spring Lately?
 
Deep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explainedDeep dive into Xtext scoping local and global scopes explained
Deep dive into Xtext scoping local and global scopes explained
 
JRuby @ Boulder Ruby
JRuby @ Boulder RubyJRuby @ Boulder Ruby
JRuby @ Boulder Ruby
 
Apache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentationApache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentation
 

Similar to A Practitioner’s guide to Hardened JavaScript

iPhone development from a Java perspective (Jazoon '09)
iPhone development from a Java perspective (Jazoon '09)iPhone development from a Java perspective (Jazoon '09)
iPhone development from a Java perspective (Jazoon '09)Netcetera
 
Lombok Features
Lombok FeaturesLombok Features
Lombok Features文峰 眭
 
Jggug ws 15th LT 20110224
Jggug ws 15th LT 20110224Jggug ws 15th LT 20110224
Jggug ws 15th LT 20110224Uehara Junji
 
iOS,From Development to Distribution
iOS,From Development to DistributioniOS,From Development to Distribution
iOS,From Development to DistributionTunvir Rahman Tusher
 
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,...
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,..."Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,...
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,...Yandex
 
Zepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksZepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksThomas Fuchs
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of JavascriptTarek Yehia
 
FI MUNI 2012 - iOS Basics
FI MUNI 2012 - iOS BasicsFI MUNI 2012 - iOS Basics
FI MUNI 2012 - iOS BasicsPetr Dvorak
 
MFF UK - Introduction to iOS
MFF UK - Introduction to iOSMFF UK - Introduction to iOS
MFF UK - Introduction to iOSPetr Dvorak
 
Xml Java
Xml JavaXml Java
Xml Javacbee48
 
Exciting JavaScript - Part II
Exciting JavaScript - Part IIExciting JavaScript - Part II
Exciting JavaScript - Part IIEugene Lazutkin
 
sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)
sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)
sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)Eugene Yokota
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012alexismidon
 
New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7Deniz Oguz
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileKonstantin Loginov
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLsintelliyole
 
Rapid JCR Applications Development with Sling
Rapid JCR Applications Development with SlingRapid JCR Applications Development with Sling
Rapid JCR Applications Development with SlingFelix Meschberger
 

Similar to A Practitioner’s guide to Hardened JavaScript (20)

Jet presentation
Jet presentationJet presentation
Jet presentation
 
iPhone development from a Java perspective (Jazoon '09)
iPhone development from a Java perspective (Jazoon '09)iPhone development from a Java perspective (Jazoon '09)
iPhone development from a Java perspective (Jazoon '09)
 
Lombok Features
Lombok FeaturesLombok Features
Lombok Features
 
Jggug ws 15th LT 20110224
Jggug ws 15th LT 20110224Jggug ws 15th LT 20110224
Jggug ws 15th LT 20110224
 
iOS,From Development to Distribution
iOS,From Development to DistributioniOS,From Development to Distribution
iOS,From Development to Distribution
 
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,...
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,..."Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,...
"Architecting and testing large iOS apps: lessons from Facebook". Adam Ernst,...
 
Zepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksZepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-Frameworks
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
 
FI MUNI 2012 - iOS Basics
FI MUNI 2012 - iOS BasicsFI MUNI 2012 - iOS Basics
FI MUNI 2012 - iOS Basics
 
MFF UK - Introduction to iOS
MFF UK - Introduction to iOSMFF UK - Introduction to iOS
MFF UK - Introduction to iOS
 
Play framework
Play frameworkPlay framework
Play framework
 
Xml Java
Xml JavaXml Java
Xml Java
 
Exciting JavaScript - Part II
Exciting JavaScript - Part IIExciting JavaScript - Part II
Exciting JavaScript - Part II
 
sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)
sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)
sbt, history of JSON libraries, microservices, and schema evolution (Tokyo ver)
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012
 
New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve Mobile
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Rapid JCR Applications Development with Sling
Rapid JCR Applications Development with SlingRapid JCR Applications Development with Sling
Rapid JCR Applications Development with Sling
 

Recently uploaded

Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Delhi Call girls
 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...APNIC
 
Enjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort Service
Enjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort ServiceEnjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort Service
Enjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort ServiceDelhi Call girls
 
AlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsAlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsThierry TROUIN ☁
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...Sheetaleventcompany
 
Challengers I Told Ya ShirtChallengers I Told Ya Shirt
Challengers I Told Ya ShirtChallengers I Told Ya ShirtChallengers I Told Ya ShirtChallengers I Told Ya Shirt
Challengers I Told Ya ShirtChallengers I Told Ya Shirtrahman018755
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girlsstephieert
 
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024APNIC
 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Servicesexy call girls service in goa
 
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebGDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebJames Anderson
 
Chennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts serviceChennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts servicesonalikaur4
 
Delhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Callshivangimorya083
 
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With RoomVIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Roomishabajaj13
 
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call GirlVIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girladitipandeya
 

Recently uploaded (20)

Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
Best VIP Call Girls Noida Sector 75 Call Me: 8448380779
 
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
'Future Evolution of the Internet' delivered by Geoff Huston at Everything Op...
 
Enjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort Service
Enjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort ServiceEnjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort Service
Enjoy Night⚡Call Girls Dlf City Phase 3 Gurgaon >༒8448380779 Escort Service
 
AlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with FlowsAlbaniaDreamin24 - How to easily use an API with Flows
AlbaniaDreamin24 - How to easily use an API with Flows
 
Dwarka Sector 26 Call Girls | Delhi | 9999965857 🫦 Vanshika Verma More Our Se...
Dwarka Sector 26 Call Girls | Delhi | 9999965857 🫦 Vanshika Verma More Our Se...Dwarka Sector 26 Call Girls | Delhi | 9999965857 🫦 Vanshika Verma More Our Se...
Dwarka Sector 26 Call Girls | Delhi | 9999965857 🫦 Vanshika Verma More Our Se...
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
Call Girls Service Chandigarh Lucky ❤️ 7710465962 Independent Call Girls In C...
 
Challengers I Told Ya ShirtChallengers I Told Ya Shirt
Challengers I Told Ya ShirtChallengers I Told Ya ShirtChallengers I Told Ya ShirtChallengers I Told Ya Shirt
Challengers I Told Ya ShirtChallengers I Told Ya Shirt
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girls
 
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 26 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
 
Rohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No AdvanceRohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
Rohini Sector 6 Call Girls Delhi 9999965857 @Sabina Saikh No Advance
 
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Saket Delhi 💯Call Us 🔝8264348440🔝
 
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
 
On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024On Starlink, presented by Geoff Huston at NZNOG 2024
On Starlink, presented by Geoff Huston at NZNOG 2024
 
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine ServiceHot Service (+9316020077 ) Goa  Call Girls Real Photos and Genuine Service
Hot Service (+9316020077 ) Goa Call Girls Real Photos and Genuine Service
 
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark WebGDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
GDG Cloud Southlake 32: Kyle Hettinger: Demystifying the Dark Web
 
Chennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts serviceChennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts service
Chennai Call Girls Porur Phone 🍆 8250192130 👅 celebrity escorts service
 
Delhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Rohini 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
 
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With RoomVIP Kolkata Call Girl Salt Lake 👉 8250192130  Available With Room
VIP Kolkata Call Girl Salt Lake 👉 8250192130 Available With Room
 
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call GirlVIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
VIP 7001035870 Find & Meet Hyderabad Call Girls LB Nagar high-profile Call Girl
 

A Practitioner’s guide to Hardened JavaScript

  • 1. Improving JavaScript (d)app security by practicing extreme modularity A Practitioner’s guide to Hardened JavaScript Tom Van Cutsem @tvcutsem
  • 2. About me • Today: Computer scientist and research director at Nokia Bell Labs • In a past life: TC39 member and active contributor to ECMAScript standards • Author of standard Proxy and Re fl ect APIs (since ECMAScript 2015) • Turning JS into a smart contracting language before Ethereum existed @tvcutsem tvcutsem.github.io
  • 3. A software architecture view of app security OAuth certi fi cate pinning cookies same-origin policy CSRF content security policy html sanitization HSTS
  • 4. A software architecture view of app security OAuth certi fi cate pinning cookies isolation functions encapsulation data fl ow dependencies modules immutability same-origin policy CSRF content security policy html sanitization HSTS
  • 5. A software architecture view of app security “Security is just the extreme of Modularity” - Mark S. Miller 
 (Chief Scientist, Agoric) Modularity: avoid needless dependencies (to prevent bugs) Security: avoid needless vulnerabilities (to prevent exploits)
  • 6. It’s all about trust It is exceedingly common to run code you don’t know/trust in a common environment Webpage Browser env (e.g. Firefox) Web server app Server env (e.g. node) Module Module Module Module Requests Files DOM Cookies
  • 7. It’s all about trust Even more critical in Web3 where code may access digital assets or wallets Webpage Browser env (e.g. Firefox) Web server app Server env (e.g. node) Module Module Module Module Requests Files DOM Cookies Smart contract dapp Blockchain env Module Module Assets Wallets
  • 8. What can happen when code goes rogue? Webpage Browser env (e.g. Firefox) Web server app Server env (e.g. node) Module Module Module Module Requests Files DOM Cookies Smart contract dapp Blockchain env Module Module Assets Wallets
  • 9. What can happen when code goes rogue? Web server app Server env (e.g. node) Module Module Requests Files npm install event-stream (source: theregister.co.uk)
  • 10. Avoiding interference is the name of the game • Shield important resources/APIs from modules that don’t need access • Apply Principle of Least Authority (POLA) to application design Webpage Browser env (e.g. Firefox) Web server app Server env (e.g. node) Module Module Module Module Requests Files DOM Cookies Smart contract dapp Blockchain env Module Module Tokens Keys
  • 11. Running example: apply POLA to a basic shared log We would like Alice to only write to the log, and Bob to only read from the log. import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = new Log() ; alice(log) ; bob(log); JS app Alice Bob log
  • 12. Running example: apply POLA to a basic shared log If Bob goes rogue, what could go wrong? import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = new Log() ; alice(log) ; bob(log); JS app Alice Bob log
  • 13. Bob has way too much authority! import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = new Log() ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can replace the Array built-in s Array.prototype.push = function(msg) { console.log(“I’m not logging anything”) ; }
  • 14. Load each module in its own environment,
 with its own set of “primordial” objects How to solve “prototype poisoning” attacks? import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = new Log() ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can replace the Array built-in s Array.prototype.push = function(msg) { console.log(“I’m not logging anything”) ; }
  • 15. Intuitions: “iframe without DOM”, “principled version of node’s `vm` module” ShadowRealms (TC39 Stage 3 proposal) ShadowRealm Host environment ShadowRealm globalThis Array globalThis Primordials* Math Objects * Primordials: built-in objects like Object, Object.prototype, Array, Function, Math, JSON, etc. Array Math
  • 16. Each Compartment has its own global object but shared (immutable) primordials. Compartments (TC39 Stage 1 proposal) Host environment Compartment Compartment Array globalThis Array globalThis globalThis Primordials* Math Objects Deep-frozen 
 Primordials Deep-frozen 
 Objects Math * Primordials: built-in objects like Object, Object.prototype, Array, Function, Math, JSON, etc. ShadowRealm ShadowRealm
  • 17. Hardened JavaScript (inspired by the diagram at https://github.com/Agoric/Jessie ) • A subset of JavaScript, building on Compartments • Key idea: no powerful objects by default. Code can only affect the outside world only through objects (capabilities) explicitly granted to it (POLA) import ‘ses’ ; lockdown(); Full ECMAScript (“WAT” JavaScript) “use strict” (“sane” JavaScript) Hardened JavaScript) JSON (“data” JavaScript) = strict-mode JavaScript - mutable primordials 
 - ambient authority (powerful globals) 
 + Compartments
  • 18. LavaMoat • Build tool that puts each of your app’s package dependencies into its own sandbox • Auto-generates con fi g fi le indicating authority needed by each package • Plugs into Webpack and Browserify https://github.com/LavaMoat/lavamoat
  • 19. Back to our example import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = new Log() ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can replace the Array built-in s Array.prototype.push = function(msg) { console.log(“I’m not logging anything”) ; } With Alice and Bob’s code running in their own
 Compartment, we mitigate the poisoning attack
  • 20. One down, three to go import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = new Log() ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; }
  • 21. Make the log’s interface tamper-proof Object.freeze (ES5) makes property bindings (not their values) immutable import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = Object.freeze(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; }
  • 22. Make the log’s interface tamper-proof. Oops. Functions are mutable too. Freeze doesn’t recursively freeze the object’s functions. import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = Object.freeze(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 23. Make the log’s interface tamper-proof Hardened JS provides a harden function that “deep-freezes” an object import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = harden(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 24. Two down, two to go import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = harden(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 25. Two down, two to go import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return this.messages_; } } let log = harden(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 26. Don’t share access to mutable internals • Modify read() to return a copy of the mutable state. • Even better would be to use a more e ffi cient copy-on-write or “persistent” data structure (see immutable-js.com ) import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 27. Three down, one to go import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 28. Three down, one to go • Recall: we would like Alice to only write to the log, and Bob to only read from the log. • Bob receives too much authority. How to limit? import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log) ; bob(log); JS app Alice Bob log // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ;
  • 29. Pass only the authority that Bob needs. Just pass the write function to Alice and the read function to Bob. Can you spot the bug? import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log.write) ; bob(log.read); JS app Alice Bob write // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ; read 𝑓𝑓
  • 30. Pass only the authority that Bob needs. To avoid, only ever pass bound functions import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log.write.bind(log)) ; bob(log.read.bind(log)); // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ; JS app Alice Bob write read 𝑓𝑓
  • 31. Success! We thwarted all of Evil Bob’s attacks. import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log.write.bind(log)) ; bob(log.read.bind(log)); // in bob.j s // Bob can just write to the lo g log.write(“I’m polluting the log” ) // Bob can delete the entire lo g log.read().length = 0 // Bob can replace the ‘write’ functio n log.write = function(msg) { console.log(“I’m not logging anything”) ; } // Bob can still modify the write functio n log.write.apply = function() { “gotcha” } ; JS app Alice Bob write read 𝑓𝑓
  • 32. Is there a better way to write this code? The burden of correct use is on the client of the class. Can we avoid this? import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log.write.bind(log)) ; bob(log.read.bind(log)); JS app Alice Bob write read 𝑓𝑓
  • 33. Use the Function as Object pattern • A record of closures hiding state is a fi ne representation of an object of methods hiding instance vars • Pattern long advocated by Doug Crockford instead of using classes or prototypes import * as alice from "alice.js" ; import * as bob from “bob.js" ; class Log { constructor() { this.messages_ = [] ; } write(msg) { this.messages_.push(msg); } read() { return [...this.messages_]; } } let log = harden(new Log()) ; alice(log.write.bind(log)) ; bob(log.read.bind(log)); JS app Alice Bob write read 𝑓𝑓 import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; alice(log.write) ; bob(log.read); (See also https://martinfowler.com/bliki/FunctionAsObject.html )
  • 34. Use the Function as Object pattern JS app Alice Bob write read 𝑓𝑓 import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; alice(log.write) ; bob(log.read);
  • 35. What if Alice and Bob need more authority? JS app Alice Bob write read 𝑓𝑓 import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; alice(log.write) ; bob(log.read); If over time we want to expose more functionality to Alice and Bob, we need to refactor all of our code. import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } function size() { return messages.length(); } return harden({read, write, size}) ; } let log = makeLog() ; alice(log.write, log.size) ; bob(log.read, log.size); size 𝑓
  • 36. Expose distinct authorities through facets Easily deconstruct the API of a single powerful object into separate interfaces by nesting objects JS app Alice Bob writer reader import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } function size() { return messages.length(); } return harden( { reader: {read, size} , writer: {write, size} }) ; } let log = makeLog() ; alice(log.writer) ; bob(log.reader); import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } function size() { return messages.length(); } return harden({read, write, size}) ; } let log = makeLog() ; alice(log.write, log.size) ; bob(log.read, log.size);
  • 37. Further limiting Bob’s authority We would like to give Bob only temporary read access to the log. import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; alice(log.write) ; bob(log.read) ; JS app Alice Bob write read 𝑓𝑓
  • 38. Use caretaker to insert access control logic import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableLog(log) ; alice(log.write) ; bob(rlog.read) ; JS app Alice Bob write read 𝑓𝑓𝑓 We would like to give Bob only temporary read access to the log.
  • 39. Use caretaker to insert access control logic We would like to give Bob only temporary read access to the log. import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableLog(log) ; alice(log.write) ; bob(rlog.read) ; // to revoke Bob’s access : revoke(); JS app Alice Bob write read 𝑓𝑓𝑓
  • 40. A caretaker is just a proxy object import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableLog(log) ; alice(log.write) ; bob(rlog.read) ; JS app Alice Bob write read 𝑓𝑓𝑓 function makeRevokableLog(log) { function revoke() { log = null; } ; let proxy = { write(msg) { log.write(msg); } read() { return log.read(); } } ; return harden([proxy, revoke]) ; }
  • 41. A caretaker is just a proxy object import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableLog(log) ; alice(log.write) ; bob(rlog.read) ; // to revoke Bob’s access : revoke(); function makeRevokableLog(log) { function revoke() { log = null; } ; let proxy = { write(msg) { log.write(msg); } read() { return log.read(); } } ; return harden([proxy, revoke]) ; } JS app Alice Bob write read 𝑓𝑓𝑓
  • 42. Membranes are generalized caretakers Proxy any object reachable from the log JS app Alice Bob write read 𝑓𝑓𝑓 msgs [] import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableMembrane(log) ; alice(log.write) ; bob(rlog.read) ; let msgs = read() []
  • 43. Membranes are generalized caretakers JS app Alice Bob write read 𝑓𝑓 msgs [] import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableMembrane(log) ; alice(log.write) ; bob(rlog.read) ; // to revoke Bob’s access : revoke(); let msgs = read() [] 𝑓
  • 44. Membranes are generalized caretakers JS app Alice Bob write read 𝑓𝑓 msgs [] import * as alice from "alice.js" ; import * as bob from “bob.js" ; function makeLog() { const messages = [] ; function write(msg) { messages.push(msg); } function read() { return [...messages]; } return harden({read, write}) ; } let log = makeLog() ; let [rlog, revoke] = makeRevokableMembrane(log) ; alice(log.write) ; bob(rlog.read) ; // to revoke Bob’s access : revoke(); let msgs = read() [] 𝑓 Deep dive at tvcutsem.github.io/membranes
  • 45. Taming is the process of restricting access to powerful APIs • Expose powerful objects through restrictive proxies to third-party code • For example, Alice might give Bob read-only access to a speci fi c subdirectory of her fi le system JS app Alice Bob restricted 
 API access Host resources full API 
 access
  • 46. These patterns are used in industry Uses taming for safe html 
 embedding of third-party content Mozilla Firefox Salesforce Lightning Moddable XS Uses membranes to isolate site origins from privileged JS code Google Caja Uses realms and membranes to 
 isolate & observe UI components Uses Compartments for safe end-user 
 scripting of IoT products Uses Hardened JS for writing 
 smart contracts and Dapps Uses LavaMoat to sandbox plugins 
 in their crypto web wallet MetaMask Snaps Agoric Zoe
  • 47. Talk summary • Think of “app security” as practicing “extreme modularity” • Modern JS apps are composed from many modules. You can’t trust them all. • Apply the “principle of least authority” to limit trust. • Isolate modules using Hardened JS & Lavamoat • Let modules interact safely using patterns such as facets, caretaker, membranes, taming, … • Understanding these patterns is critical in Web3 where code may have direct access to digital assets JS app Environment Module Module Shared resources
  • 48. Tom Van Cutsem @tvcutsem Thanks for listening! Improving JavaScript (d)app security by practicing extreme modularity A Practitioner’s guide to Hardened JavaScript
  • 49. Acknowledgements • Mark S. Miller (for the inspiring and ground-breaking work on Object-capabilities, Robust Composition, E, Caja, JavaScript and Secure ECMAScript) • Marc Stiegler’s “PictureBook of secure cooperation” (2004) was a great source of inspiration for this talk • Doug Crockford’s Good Parts and How JS Works books were an eye-opener and provide a highly opinionated take on how to write clean, good, robust JavaScript code • Kate Sills and Kris Kowal at Agoric for helpful comments on earlier versions of this talk • The Cap-talk and Friam community for inspiration on capability-security and capability-secure design patterns • TC39 and the es-discuss community, for the interactions during the design of ECMAScript 2015, and in particular all the feedback on the Proxy API • The SES secure coding guide: https://github.com/endojs/endo/blob/master/packages/ses/docs/secure-coding- guide.md
  • 50. Further Reading • Compartments: https://github.com/tc39/proposal-compartments and https://github.com/Agoric/ses-shim • ShadowRealms: https://github.com/tc39/proposal-realms and github.com/Agoric/realms-shim • Hardened JS (SES): https://github.com/tc39/proposal-ses and https://github.com/endojs/endo/tree/master/packages/ses • Subsetting ECMAScript: https://github.com/Agoric/Jessie • Kris Kowal (Agoric): “Hardened JavaScript” https://www.youtube.com/watch?v=RoodZSIL-DE • Making Javascript Safe and Secure: Talks by Mark S. Miller (Agoric), Peter Hoddie (Moddable), and Dan Finlay (MetaMask): https://www.youtube.com/playlist?list=PLzDw4TTug5O25J5M3fwErKImrjOrqGikj • Moddable: XS: Secure, Private JavaScript for Embedded IoT: https://blog.moddable.com/blog/secureprivate/ • Membranes in JavaScript: tvcutsem.github.io/js-membranes and tvcutsem.github.io/membranes • Caja: https://developers.google.com/caja