Go as an object-capabilities language.

849 views
Skip to first unread message

Frithjof Schulze

unread,
Jun 6, 2014, 11:06:17 AM6/6/14
to golan...@googlegroups.com
I want to argue that Go is perfectly suited to be used as an object-capabilities language and that value can be gained from thinking about the language in terms of Object-Capabilities. In fact, a lot of the Go code I have seen uses the language in this way -- because this naturally makes the code modular and testable -- but never makes the concept explicit. 

Below I will try to explain what I mean with object-capabilities language. If what I write makes enough sense, you might want to read the Joe-E paper [1] about a Java subset as a capabilities language or watch Marc Stiegler's "The Lazy Programmer's Guide to Secure Computing" Google Tech Talk about JavaScript and object-capabilities. Think about how perfectly these concepts translate to Go's use of interfaces and channels while reading/watching.

Please also tell me if all these ideas are too obvious to merit a name, or are obviously wrong. I guess I am mainly asking for comments and want to suggest that people look into these ideas.

The word capability in "object-capability language" means the capability to perform an action on some "object". E.g. if I have an os.File object I can read and write to that file. If a package isn't allowed to use a few dangerous packages ("os", "os/*", "unsage", "io/ioutil", "net") all "ambient authority" is removed and it becomes impossible to create new capabilities. Instead the package can only be provided with capabilities via an argument in a function call or via a channel. This makes it possible to split the program into modules that have only the capabilities/privileges they need to have, making it easy to follow the principle of least privilege and to isolate "untrusted" third-party packages. It also supports modular reasoning, testing etc.

Because so much of Go's standard library is written around a few key interfaces (io.Reader, io.Writer etc.) it should be rather easy to define a "tame" subset of packages. In comparison, it was a major effort for the Joe-E project to define a tame subset of the Java standard library.

In Go channels are a new way to provide modules with capabilities, that is not present in most other languages.

Go strict typing also makes it impossible to "forge" capabilities, if the package "unsafe" is forbidden (type asserting and conversions might be a problem though). Wrapping types makes it easy to provide subsets of capabilities, or to create revocable capabilities.

The objects-capabilities language people (Marc S. Miller, Marc Stiegler, David Wagner and many others) came up with a number of "patters" to handle capabilities, that (I think) never really got mainstream attention, but should be ideally suited for Go.

egon

unread,
Jun 6, 2014, 11:35:23 AM6/6/14
to golan...@googlegroups.com
Too long, didn't read. (not yet at least)

What I mean is that your argument is too long for most people to read.

Try to give two real-world examples where Go would benefit from it, and examples in Go. It gives a better ground for arguing about a specific thing. I'm aware of the examples in the paper, but it would be better to repeat those examples, to avoid needing to read the full paper.

From preliminary overview, wouldn't you get better security from having multiple applications (services) and set the limits based on the application?

+ egon

Frithjof Schulze

unread,
Jun 6, 2014, 2:24:39 PM6/6/14
to golan...@googlegroups.com
On Friday, June 6, 2014 5:35:23 PM UTC+2, egon wrote:
Too long, didn't read. (not yet at least)

What I mean is that your argument is too long for most people to read.

Try to give two real-world examples where Go would benefit from it, and examples in Go. It gives a better ground for arguing about a specific thing. I'm aware of the examples in the paper, but it would be better to repeat those examples, to avoid needing to read the full paper.

I am sure you are right. I had the vague plan to write this up nicely and with examples repeatedly, but I never came around to actually do so. Today I decided to just toss the idea out. And the paper is worth reading :)
 
From preliminary overview, wouldn't you get better security from having multiple applications (services) and set the limits based on the application?

Sure. But thinking about capabilities at the level of POSIX processes involves so many subtleties. Just look at the work necessary to set up Chrome's sandboxes or at FreeBSD's capsicum. The modern statically typed and type-safe languages in comparison provide the concept of capabilities basically for free.

-Frithjof

Matt Harden

unread,
Jun 6, 2014, 8:22:19 PM6/6/14
to Frithjof Schulze, golang-nuts
Type safety is helpful, but since it's possible to create race conditions in "safe" code using goroutines, all bets are off when running untrusted source code. Code with a race could theoretically do anything at all.


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

egon

unread,
Jun 9, 2014, 2:56:33 AM6/9/14
to golan...@googlegroups.com
Finally had the time to read the paper. (Also, as a note, I'm not a security expert.)

To me, the only proper way to ensure good security is to have at least two machines, where one is dedicated to trusted code and the other to untrusted code.

If you want to protect one module from other module you shouldn't have shared memory nor shared runtime. As a trivial example of untrusted code "for {}" could take the system down, if that isn't the case. Sandboxes seem to be a much better approach (if you don't have multiple machines available).

The effort required to setup sandboxes is something that can be improved, one could imagine:

box := nacl.New()
defer box.Shutdown()
box.MemoryLimit = 2*nacl.MB
box.AddMethod("print", func(v string, vals... string){
fmt.Printf(v, vals...)
})

box.Load(untrustedcode)
box.Run()

select {
case <-box.Wait():
// succeeded
case <-time.After(1*time.Second):
// process took too long
box.Stop()
}


+ egon

timc...@gmail.com

unread,
Oct 5, 2015, 11:18:12 AM10/5/15
to golang-nuts
Did these thoughts go any further?  I'm increasingly convinced that OCap are required for IoT applications, and I'm looking for implementations that work in a distributed world and continue to be supported.

Egon

unread,
Oct 5, 2015, 3:37:57 PM10/5/15
to golang-nuts
I'm not sure which properties of OCap you need? Why do you think IoT needs it?

AFAIK, nothing happened from this discussion.

+ Egon

Tim Coote

unread,
Oct 17, 2015, 1:10:13 PM10/17/15
to Egon Elbre, golan...@googlegroups.com
Oops.

Reasonable response. Fwiw, my starting point had been the distributed programming language E.

You're right about a concrete example. So, here's a scenario:

My wife wants to lend my 'lawnmower' to a neighbour to cut her grass. As an IoT 'Thing', most of the intelligence of my lawnmower (efficiency measurements, grass height for my area, anti-pet-muck-spreading-awareness, etc) is not embedded in the physical lawnmower, but delivered as needed from other 'Things'. So the 'lawnmower' is more than just the physical piece of tin (although that's not super-relevant in this example).

In order to lend my mower and to ensure that it is used properly, and probably to remind me who I lent it to last, I'd like to embed the authority delegation into the lending process, rather than have a separately managed security model.

It seemed to me that the OCap model of authority delegation, with what used to be the 'caretaker pattern' and is now coalescing into 'membranes', to enable rights revocation (causing the mower to make its way home), is a good fit as it ensures that the development process considers the security angles.

On 8 October 2015 at 20:28, Egon Elbre <egon...@gmail.com> wrote:
On Thursday, 8 October 2015, Tim Coote <timc...@gmail.com> wrote:
It's really the programming model, and the consequent administration. Typical usecases would be lending Things to others for a while, and embedding the security model in the functional description, rather than having a separate process for managing the security.


Note real-world concrete examples work much better for explaining new things. "Things" are too abstract.
 


Too much ambient authority with ACLs and too complicated to set up sharing.

if it's a no-go, then there's always DrSES, I suppose.  

Note, you forgot reply all :)

I don't think it belongs in the language, there are many ways of implementing it. Although it would be perfect as a library... It could be implemented on top of NaCl or alternatively implemented as a Go VM or interpreter. OCap can be added as comments, func calls to the runtime or something else, depending on the needs.

So it's not a "no-go", but rather "someone needs to implement it and make it usable".




--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/q-r8ZLN_r_c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Bakul Shah

unread,
Oct 17, 2015, 1:56:09 PM10/17/15
to Tim Coote, Egon Elbre, golan...@googlegroups.com
For IoT kind of use cases I think you'd first want to worry about such things at the communication protocol level rather than at the implementation language level. For instance, what you ideally want is a) the lawnmower can only be turned on with a specific key, b) the key can not be duplicated and c) it can be revoked by the owner. Not unlike how a card key works in a hotel. The implementation language of a single component doesn't matter.
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
Message has been deleted

Jason E. Aten

unread,
Oct 21, 2015, 7:41:13 AM10/21/15
to golang-nuts, egon...@gmail.com, timc...@gmail.com
Hi Tim,

Capnproto is an object-capability based system (see https://sandstorm.io), and Ross Light at Google just contributed a go-capnproto2 library that fully implements the spec. Seehttps://github.com/zombiezen/go-capnproto2/  He mentioned he was also working on grpc transport support for it, but that part may not be done yet (you could ask him about that).
Reply all
Reply to author
Forward
0 new messages