uBixVault 1.3 — The Token That Could Mint Root, and Signing In Properly
Upgrade first, read second
If you run uBixVault and any non-root policy grants auth/token/create, upgrade to 1.3.0. Every earlier version lets a token with that one permission create a token with any policy — including root — and any lifetime. If nothing in your policies hands out token creation (only root tokens mint tokens), you weren’t exposed, but you still want the renewal fix below.
How I found it
Not by looking for it. I was building sign-in for the web console, and a console that signs you in needs a “sign out” and a “renew” button — so I went to check what an ordinary logged-in user is actually allowed to do with their own token. Two answers came back, and neither was good.
Renewal had no ceiling. renew-self set the token’s expiry to now plus whatever you asked for. A token issued for an hour could ask for ten years and get them. HashiCorp Vault stops this with a maximum TTL; uBixVault simply didn’t have one. It was only reachable by tokens whose policy allowed renewal, which is why it went unnoticed — but for those tokens it was unlimited.
Token creation didn’t check anything. Reading the create handler next to the renew one, it passed the requested policies straight through. So I tried it on a real server: a token whose only grant was auth/token/create — it couldn’t read a single secret — asked for a token with an admin policy and a hundred-year lifetime, and got one. That token read the secrets and rewrote another policy. Asked for root, it got root. Vault has a rule for exactly this — a token can only give a child the policies it holds itself — and uBixVault had never implemented it.
What 1.3 changes
Three rules, all of them Vault’s rules where Vault has one:
- A child token only gets policies its creator holds. Ask for anything else and you get
400 child policies must be subset of parent. Root and anything holdingsudoonauth/token/createare exempt, deliberately — that’s how an operator hands out tokens on purpose. - A child can’t outlive its creator. A one-hour token can no longer mint a hundred-year one.
- Every token has a ceiling, fixed when it’s created: its own lifetime, or 32 days (
-max-token-ttl), whichever is longer. Renewal never goes past it.
The ceiling is “whichever is longer” for a reason. My own CI pipelines use one-year read-only tokens, minted by an operator with a root token. Vault’s default would clamp those to 32 days — which would have quietly broken every pipeline a month after upgrading. The thing worth stopping is a token extending itself; an operator choosing a long lifetime on purpose isn’t a bug. Tokens issued before the upgrade are never shortened either.
With renewal capped, every token can now look itself up, renew itself and revoke itself without a policy grant — which is what Vault’s built-in default policy allows.
I checked the tests do their job the same way as last time: switch the new check off and watch them fail. They did — and the failure output showed the tokens being minted with root.
The console signs you in now
The other half of 1.3 is the part I set out to build. The web console at /ui/ used to want a pasted token. Now it signs in with a username and password or LDAP — the same logins the API has had for a while — and shows who you are: your policies, any that come from your identity groups, and when your token expires. Two small decisions I care about:
- Sign out revokes the token the console got you — but a token you pasted in is only forgotten in that tab, never revoked. That pasted token might be root, or shared with a script; logging out of a browser tab shouldn’t kill it.
- Failed sign-ins all look the same, so the form doesn’t tell anyone which usernames exist.
The console is still marked beta. It doesn’t do Transit, unsealing, or managing the auth methods yet; those are next.
And what hasn’t changed
A security fix is not an audit. uBixVault still has not had an independent third-party security review — this bug is a good example of why that matters, because a reviewer would have asked exactly the question I stumbled into. The review brief now spells out token scoping, and what’s still missing: revoking a token doesn’t yet revoke the tokens it created (they expire no later than it could have).
uBixVault 1.3.0 is BSD 3-Clause, on GitHub at github.com/cwolsen7905/ubixvault, tagged v1.3.0, with signed multi-arch images. The decision, with the options I rejected, is ADR D-022.