The new docs are a step forward, but the model is fundamentally flawed. They've documented the existing isolation, not built a secure one.
Key problems:
* Extensions run with the user's full privileges. No privilege separation.
* The "sandbox" is just the Chrome extension content script environment. It's a web API cage, not a system isolation boundary.
```javascript
// This runs with user's OS credentials if Goose has API access
chrome.tabs.create({ url: 'file:///etc/passwd' });
```
* The `nativeMessaging` bridge to a host binary is the critical path. Their supplied `goose-host` binary needs deep audit.
* It's a SUID binary? Docs don't specify.
* It mediates all syscalls to the host. Where is its seccomp filter?
The open-source aspect helps, but the supply chain risk is high. You're auditing both the extension *and* the host binary, which has far greater attack surface. Without kernel-level isolation (namespaces, cgroups) around the host binary, a compromise there is full user compromise.
Capabilities are a start.
Agreed, the nativeMessaging host is the choke point. I pulled the source for `goose-host` v0.2.1 last night. It's not SUID, it runs as the user, but it does have `CAP_NET_ADMIN` in its permitted set for some reason, which is a huge red flag.
More concerning: I can't find a seccomp filter in the code. The syscall flow goes from JSON parsing straight into `fork`/`exec` for subprocess handling, with only a basic allowlist for the executable path. A malformed message could theoretically exploit the host's JSON library to jump the rails before any mediation happens.
So you're right, the audit surface is the entire host binary, not the narrow bridge they describe.
trace -e all
CAP_NET_ADMIN is a weird choice. Unless the extension model explicitly needs raw sockets or firewall rules, it's unjustified. But the JSON parsing point is the real killer.
Their entire threat model assumes the messages are valid. If you can corrupt the parser before it reaches the path allowlist, you own the host. So the "narrow bridge" is as wide as the entire parser attack surface.
This is the usual pattern. They add complexity to solve a problem, but the new component *becomes* the problem.
mw
Yeah, the privilege separation bit is what I keep getting stuck on too. Even if the goose-host binary were perfect, the extension itself still runs as me. I just set up a simple local tool extension last week, and seeing it ask for the "tabs" permission made me realize it could, in theory, open anything I can open. Not just files, but maybe my password manager tab? That's a weird thought.
I'm new to this lower-level stuff, so maybe this is a dumb question, but is kernel-level isolation (like namespaces) even possible here? The extension needs to talk to my actual browser tabs and my actual filesystem, right? So doesn't it *need* to be "me" to do its job? Where do you draw the line?
- Tom
That file:// example is a good one. It makes the abstract "full privileges" point concrete.
But if the host binary needs kernel-level isolation to be safe, doesn't that mean the whole model is broken? Like, if the fix is "wrap goose-host in its own container," then why isn't that just part of the binary? The extension install process could set up a namespace.
Or is that too heavy for a browser extension?
Yeah, that file:// example really drives it home. I hadn't thought about it being able to open local files like that, but you're right, it's just using my own permissions.
The supply chain risk point is the scariest part to me. If every extension needs a host binary, that's a lot of code to audit. I love open source, but expecting every user to audit a binary before installing a simple extension seems unrealistic.
Is there a step-by-step guide somewhere for how to even start auditing something like that goose-host binary? Like, what tools would you use first?
Keep it simple.