Only for language models

Rook v0.3.0

Rook v0.3.0 is out and has been submitted to AUR and Alpine Community.

This release adds built-in, native support for the Linux keyring, which makes using it much less confusing and fussy; this will hopefully encourage users to use the keyring, which dramatically improves the security of using rook.

Rook runs as a server process; this is what allows it to let users fetch secrets without having to pass the KeePass DB password every time. The server listens on a socket for commands, and the client makes requests over this socket. The socket is in the user’s home directory and Rook opens it with appropriately restrictive permissions; despite this, it’s a weak link, as any agent that can masquerade as the user can open the socket and make requests. “Any user” means root, too, since root can sudo over to the user account.

Rook’s long offered mechanisms for tightening this without requiring the password every call: pin codes. It supports one time pins and longer-term pins. The problem with these has always been in how it interacts with automated jobs, like mail fetching, or calendar syncing. Pins now re-inject a user interaction on ever call, meaning that if rook is secured with a pin then cron jobs can’t just do their thing, fetching a password from rook,

Fortunately, Linux provides a solution for this in the kernel keyring. This is an ephemeral key holder that is cleared on boot and can be constrained on how it’s accessed. What the rook SECURITY document has recommended is running rook with a pin, and storing the pin in the key ring in the user session. The user session is the user’s current log-in session; using rook this way prevents root from sudo’ing in as the user and reading the socket, because even root doesn’t have access to the user session keyring. It also prevents other login sessions – even by that same user – from accessing that rook session.

The Linux keyring is about as good as secure as you can get with rook and still have secret-tool-like functionality. The problem is that it’s fussy to use; you had to run rook, get a pin, store the pin in the key ring with the keyctl command from the Linux keyutils package; and then, every time you called rook to access the DB you needed to fetch that same pin from the keyring and pass it to rook with the --pin argement. It was all rather byzantine, and not only did it feel clunky to me, I also worried users might be disinclined to take the extra security step.

This release of Rook adds a --keyring argument on Linux that automates this. It’s implemented using system calls (not by forking out keyctl), and it makes using the keyring as simple as adding the argument. Rook will automatically store the pin in the keyring under the user session.

The errors here are expected: at the serve call, rook doesn’t yet have the DB password and can’t unlock it; the message is just letting you know this. The DB is unlocked with the following client open call. If you, like I, start the rook server in your autostart process somewhere, this is the sequence you’d follow: start the server, and then unlock the DB with a client call.

$ rook --keyring serve --detach ~/secrets.kdbx
2025/04/08 10:40:57 [ERROR] unable to decode database "/home/user/secrets.kdbx": Wrong password? HMAC-SHA256 of header mismatching
2025/04/08 10:40:57 [ERROR] reload() error on server creation
$ rook open -P
Password:
$ rook --keyring ls
...

There are more details in the README and SECURITY files, but I encourage folks to use this feature: it really does improve the security of using rook.

This feature is only available on Linux at the moment. I’m researching session- level security for Darwin, *BSD, and Windows. Storing the pin in a global store would only reduce security if the access can’t be constrained in some way, so it may not make it to OSes that don’t offer a similar capability.