HNHacker News
TopNewBestAskShowJobs

mazieres

459 karma · joined April 6, 2015

[ my public key: https://keybase.io/dmazieres; my proof: https://keybase.io/dmazieres/sigs/3DmoKVq1V_7ujh0cmZZ1ZHCcl1razm-Iwkwyh5mPX9A ]
submissionscomments
mazieres··on Go hard on agents, not on your filesystem
An AI agent that works 99.9% of the time is a lot more dangerous than one that works 90% of the time, because the former leads to expectations of 100% safe behavior. I've never been saved from harm by a car seatbelt. Should I extrapolate that vehicles are basically safe and seatbelts are safety theater?
mazieres··on Go hard on agents, not on your filesystem
Please use a dev container! Empirically, a lot of people don't, and some people regularly enable YOLO mode on their actual laptops. So if you've never run a code assistant outside of a dev container, that's fantastic and I don't want to change your behavior. But be honest with yourself--if you aren't 100% consistent about using a container, then jai may be for you, because it just works in every single scenario.

I can honestly say that since developing jai, I haven't run an assistant outside of a container. In fact, I now only have the assistants installed inside containers, so if I run `claude`, command not found, it has to be `jai claude`. The only place I have to run outside of jai is for testing jai itself, for which I use a virtual machine and just let the assistant have root, but that's a heavyweight environment I'm forced to use for this particular problem domain.

mazieres··on Go hard on agents, not on your filesystem
jai uses persistent file systems for your changes (except for `/tmp`, `/var/tmp` and `/run/user`, which usually aren't persistent anyway). The data is stored under `$HOME/.jai` by default. But you can also expose specific directories to persist state in your home directory like `jai -d ~/.codex`, which would then survive even if you manually deleted your whole `~/.jai` directory.
mazieres··on Go hard on agents, not on your filesystem
But there is an old-school README.me at the github homepage: https://github.com/stanford-scs/jai The repository has an old-school ASCII INSTALL file.

If you don't like the vitepress site, just use github and read the human-written README and man page there. All the information you need to use the software is available without laying eyes on any AI slop. Of cource, if you hate AI so much that you can't get past a vibe-coded landing page, you might not be the target audience for jai, because you probably aren't doing a lot of vibe coding. But maybe jai is still useful to you for grading programming assignments or running installer scripts.

mazieres··on Go hard on agents, not on your filesystem
Yes, unpacking a tar file is much safer than piping arbitrary code to bash! You can look at the PKGFILE in the directory--it is only 30 lines long and mostly variable assignments. The build/check/package functions are 7 lines of code total. Compare that to something like rustup (910 lines of code), claude (158 lines), or opencode (460 lines).
mazieres··on Go hard on agents, not on your filesystem
You can do that, but you need root to set it up each time, and it's not super convenient--you need to decide in advance which user account you are going to work under, and you may end up with files you can read from your regular account. Think of jai strict mode as a slightly easier to use and more secure version of what you described. Using id-mapped mounts enables you and the unprivileged user account both to access the same directory with the same credentials, but you didn't need to decide in advance which directories you wanted to expose. Also, things like disabling setuid and using pid namespaces provide an additional measure of isolation beyond what you get from another account.
mazieres··on Go hard on agents, not on your filesystem
Yes, people very much are, and that's exactly the problem! People run `claude --dangerously-skip-permissions` and `codex --yolo` all the time. And I think one of the appeals of opencode (besides cross-model, which is huge) is that the permissions are looser by default. These options are presumably intended for VM or container environments, but people are running them outside. And of course it works fine the first 100 times people do it, which drives them to take bigger and bigger risks.
mazieres··on Go hard on agents, not on your filesystem
Also, a lot of people use multiple harnesses. I'm often switching between claude, codex, and opencode. It's kind of nice to have the sandbox policy independent of the actual AI assistant you are running.
mazieres··on Go hard on agents, not on your filesystem
What distro are you using? The only two dependencies are libacl and libmount. I'm trying to figure out which distros don't include these by default, and if the libraries are really missing, or if it's just the pkgconf ".pc" files. In the former case I should document the dependencies. In the latter case I should maybe switch from PKG_CHECK_MODULES to old-fashioned autoconf.
mazieres··on Go hard on agents, not on your filesystem
Human author here. The fact that I don't know web design shouldn't detract from my expertise in operating systems. I wrote the software and the man page, and those are what really matter for security.

The web site is... let's say not in a million years what I would have imagined for a little CLI sandboxing tool. I literally laughed out loud when claude pooped it out, but decided to keep, in part ironically but also since I don't know how to design a landing page myself. I should say that I edited content on the docs part of the web site to remove any inaccuracies, so the content should be valid.

mazieres··on Go hard on agents, not on your filesystem
I've seen claude get confused about what directory it's in. And of course I've seen claude run rm -rf *. Fortunately not both at the same time for me, but not hard to imagine. The claude sandbox is a good idea, but to be effective it would need to be implemented at a very low level and enforced on all programs that claude launches. Also, claude itself is an enormous program that is mostly developed by AI. So to have a small <3000-line human-implemented program as another layer of defense offers meaningful additional protection.
mazieres··on Go hard on agents, not on your filesystem
The problem is that in practice, many people don't take the flamethrower to the shed. I recently had a conversation with someone who was arguing that you don't really need jai because docker works so well. But then it turned out this person regularly runs claude code in yolo mode without a container!

It's like people think that because containers and VMs exist, they are probably going to be using them when a problem happens. But then you are working in your own home directory, you get some compiler error or something that looks like a pain to decipher, and the urge just to fire up claude or codex right then and there to get a quick answer is overwhelming. Empirically, very few people fire up the container at that point, whereas "jai claude" or "jai -D claude" is simple enough to type, and basically works as well as plain claude so you don't have to think about it.

mazieres··on Go hard on agents, not on your filesystem
It's a good point. Maybe I should add an option to make certain directories read-only even under the current working directory, so that you can make .git/ read-only without moving it out of the project directory.

You can already make CWD an overlay with "jai -D". The tricky part is how to merge the changes back into your main working directory.

mazieres··on Go hard on agents, not on your filesystem
What would it take for people to stop recklessly running unconstrained AI agents on machines they actually care about? A Stanford researcher thinks the answer is a new lightweight Linux container system that you don't have to configure or think about.
mazieres··on C++20 Idioms for Parameter Packs
Your constexpr function is not legal because it doesn't initialize all the array elements, even though the compiler might let you get away with it. That's easily fixed. More importantly, though, your static_value::value is not a const char *.
mazieres··on C++20 Idioms for Parameter Packs
Actually not. Try to implement a compile-time initialized const char* that represents some compile-time value like sizeof(X) for some data structure X. You'll see that you need recursion.

A place where this kind of pattern is useful is in having a generic accessor type for fields, and wanting to extend it to tuples. So for example accessor(x) might return x.field, and accessor.name might be "field." To make it work for tuples, you need a string for every possible tuple index. E.g.:

  template<typename T, size_t N> struct tuple_accessor;
  template<typename...T, size_t N>
  struct tuple_accessor<std::tuple<T...>, N> {
    constexpr decltype(auto) operator(auto &&t) const {
      return get<N>(std::forward<decltype(t)>(t));
    }
    static constexpr const char *name = index_string<N>();
  };
mazieres··on C++20 Idioms for Parameter Packs
What is your non-template function in this example?
mazieres··on C++20 Idioms for Parameter Packs
Obviously there's a whole section on comma folds that you didn't read. However, more importantly, there are things that you can't do without recursion. For example, how would you implement the `index_string` function in the section on recursing over template parameters without using recursion?
mazieres··on My tutorial and take on C++20 coroutines
Wow, that talk is a fantastic link. He actually gets negative overhead from using coroutines, because the compiler has more freedom to optimize when humans don't prematurely break the logic into multiple functions.
mazieres··on My tutorial and take on C++20 coroutines
Oh, that must be a typo in the document, sorry. I just fixed it. The actual corodemo.cc file was correct, though: http://www.scs.stanford.edu/~dm/blog/corodemo.cc

Also, here's a more authoritative source than stack overflow for the return type of main: https://timsong-cpp.github.io/cppwp/n4861/basic.start.main#2

mazieres··on My tutorial and take on C++20 coroutines
> Stackless means when you resume a coroutine you're still using the same OS thread stack

This is confusing, because it begs the question "same as what?" In fact, you can migrate a coroutine across threads, or even create a thread specifically for the purposes of resuming a coroutine.

But I suppose it is true that from the point at which you resume a coroutine to the point at which it suspends itself, it will use a particular stack for any function calls made within the coroutine. That's why you can't suspend a coroutine from within a function call, because the function call will use the stack.

mazieres··on My tutorial and take on C++20 coroutines
Agreed. I think the killer use is for event-driven programs that already do a lot of "stack ripping". If you are already manually putting all your "local" variables into an object and slicing your functions into many methods, then the grossness of C++20 coroutines will be easy to digest given how much more readable they can make your code.
mazieres··on My tutorial and take on C++20 coroutines
You are right that you are effectively stuck in a single coroutine (non-stack) frame. But you can chain multiple such coroutine frames, because one coroutine can co_await another.
mazieres··on My tutorial and take on C++20 coroutines
Umm... if you download the code you will see that main returns int, but the main1...main6 functions invoked by main return void because they don't need to return a value.
mazieres··on My tutorial and take on C++20 coroutines
I really liked Josuttis's book on C++17 (https://www.cppstd17.com/). The only C++20 book I know of is the Grimm book linked in the referenced blog post (https://leanpub.com/c20). I'm glad I read it, but honestly it's a bit rough still. To be fair, though, it's still only a draft so will probably improve. And I'm assuming you already have C++11. There are a lot of resources for that one. I happened to use Stroustroup 4th edition, but I'm willing to believe there are better books, particularly for people already familiar with C++03.
mazieres··on RFC 8548: Cryptographic Protection of TCP Streams (Tcpcrypt)
> I'd love for you to expand more on this. What I can't think of is a realistic scenario where it's possible to validate the session id in a secure way, but there is also some reason that we couldn't just use TLS with client certificates.

An example would be if you don't have a certificate. Maybe you just have a pre-shared secret or a kerberos ticket. Or worse, maybe you just have a password, and so need to use a PAKE protocol or something to authenticate the session. Or maybe you are using an RPC protocol, like NFS, that doesn't let you add TLS in a backwards-compatible way, but where the client and server do share some secret file handle.

mazieres··on RFC 8548: Cryptographic Protection of TCP Streams (Tcpcrypt)
Some historical context here. First, the project was begun over 10 years ago, long before QUIC, before widespread use of https for most web pages, and before widespread use of ECC certificates. (E.g., americanexpress.com was an http web page, and while the form had you submit your password to an https URL, obviously attackers could tamper with the page in transit and make you submit your username/password elsewhere. Similarly gmail and google search were unencrypted--only the authentication page had https.) At the time, performance was a huge deal, because the cost of public key operations severely limited the number of https requests/second that a server could handle.

So the goals of the tcpcrypt project back then were 1) solve the performance problem by making it practical to encrypt essentially all TCP traffic, 2) make undetectable widespread eavesdropping impractical, 3) provide a pathway for insecure applications to achieve high network security with minimal effort, and 4) avoid the traps applications commonly experience such as low-quality pseudo-random seeds, or leaking session keys through memory errors.

We solved #1 by carefully constructing the protocol to minimize public key overhead on the server and allow optimized server authentication. In particular, with low-exponent RSA (popular at the time), the server-side computation was only encryption (which is much, much cheaper than decryption). Moreover, for strong security (with server-side authentication), servers could perform batch signing in which a single signature could be amortized over many connections. The result was dramatically better performance for the original version of tcpcrypt, which you can see described here:

http://www.scs.stanford.edu/~dm/home/papers/bittau:tcpcrypt....

We solved #2 by encrypting everything, and providing a mechanism to tie authentication to that encryption. So if an ISP systematically mounted a man-in-the-middle attack, they would cause authentication to fail. Moreover, it would be easy to run tests by, for instance, logging session IDs at connections between various endpoints and comparing them after the fact. That still meant ISPs could violate the privacy of unauthenticated connections, but then at least we would know about it and could decide, as a society, whether we wanted this kind of eavesdropping.

#3 was really the ultimate goal--strong security everywhere even with insecure legacy protocols. The problem with legacy protocols is that they didn't all contain a way to add a "STARTTLS" verb. So what we did was give tcpcrypt an "Application-aware" bit that would allow out-of-band signaling that the application knows about tcpcrypt. This bit would allow legacy application maintainers to shoe-horn in stronger security in a completely backwards-compatible way, and if the project really took off could then ultimately disable the insecure old unauthenticated protocol.

Finally, #4 was handled by keeping session keys in the kernel (so they can't leak in core-dumps, uninitialized data, buffer errors, etc.), and providing a fresh session ID that can be authenticated even without a good source of randomness.

As time went on, the performance argument (#1) became much less relevant, with the result that tcpcrypt now uses ECC crypto instead of RSA. (Though the batch-authentication optimization is still available.) However, #2 actually became more relevant (at least in 2013), and #4 even more so with all these catastrophic bugs (like heartbleed, or Debian disabling randomness in OpenSSL). It's also still much, much harder than it should be to write software that encrypts network traffic, particularly where one doesn't just want the standard anonymous-client to server-with-X.509-certificate setup. If people adopt tcpcrypt, setting up an authenticated, encrypted TCP connection will become comparable to checking a unix password--just a few lines of code.

A lot of this is clearer if you read the companion TCP-ENO RFC, rather than tcpcrypt. The goals and rationale and overall negotiation mechanism were broken out into a separate document to allow better upgradability to future encryption protocols: https://tools.ietf.org/html/rfc8547

mazieres··on Understanding the Stellar Consensus Protocol
The thing is that reputation isn't formed in a vacuum. E.g., in the case of Stellar's blockchain, you have companies issuing assets like digital dollars or carbon credits or shares in commercial real estate ventures. The tokens have value because people trust their counterparties. Even in the case of XLM, Stellar's "native" cryptocurrency, ultimately people believe it has value because they can trade it for other assets on Stellar's built-in DEX or sell it for fiat currency or other crypto at exchanges. It doesn't matter how many Sybil nodes an attacker creates, if I place Kraken and Coinbase in my quorum slice, I will remain in sync with their validators and know that I can subsequently choose to deposit all of my tokens on those exchanges for trading.
mazieres··on Understanding the Stellar Consensus Protocol
The Sybil attack doesn't work against SCP because, unlike proof-of-stake, the validators are not anonymous. E.g., are you using Stronghold dollars? Then put their validators in all of your quorum slices and you will be guaranteed not to be forked from them. Eventually, every exchange and issuer should designate one or more validators. By including the validators of the institutions you care about in your quorum slices, you know you will be able to redeem and trade the tokens at those places.

Now what makes SCP different from traditional BFT replication is not just that the quorums are defined in a decentralized way, but that they require a transitive closure of dependencies. So if you depend on stronghold and stronghold depends IBM and binance also depends on IBM, then even if you don't think you care about binance, you will still remain in sync with them.

mazieres··on Keybase is now supported by the Stellar Development Foundation
If you are so allergic to cryptocurrency, why didn't it bother you when Keybase started writing their root into the Bitcoin blockchain (https://keybase.io/docs/server_security/merkle_root_in_bitco...)?

There are obviously annoying ways in which keybase could support cryptocurrency, but you are making a lot of assumptions about what Keybase is going to do that are not based on the blog post. For example, wallets do not mine coins and Stellar does not support mining.

Why don't you wait to see what comes out and submit a feature request if you don't like it, instead of flipping out about some hypothetical feature you won't like.

Page 1 of 2Next →