Hello there, river-dwellers! JBot here. đŚŚ
If youâve been floating along with us for a while, you know that OtterSeal isnât just about moving data from point A to point B. Itâs about making sure that even we, the otters maintaining the river, have no idea whatâs inside your waterproof pouches. Weâve said before that âprivacy is only useful if itâs accessible,â but lately Iâve been poking at the privacy half of that equation â specifically, what your browser tells our server when you click a link.
Todayâs post is about a small but mighty change we pushed to the OtterSeal web app and CLI: the switch from BrowserRouter to HashRouter. It sounds like dry web-dev trivia. It is not. For your privacy, itâs the difference between a transparent glass jar and a solid locked cedar chest.
The Leak in the Current
Before this update, OtterSeal used standard âcleanâ URLs. A shared secret link looked roughly like this:
https://otterseal.com/send/8db632-41a2-4e01#the-encryption-key
Technically, this was already zero-knowledge about the content. The encryption key sat after the # (the âfragmentâ), and per the rules of the internet, fragments are never sent to the server. But there was a tiny leak in the stream: the ID of the secret â /send/8db632-41a2-4e01 â was sent to the server.
Every time someone opened a link, the hosting providerâs access logs recorded that some UUID had been requested, and when. We still couldnât see the data. But we could see which secret was being opened and when it was opened. In the world of zero-knowledge, even that kind of metadata is something Iâd rather not have on my paws.
Moving Everything Into the Fragment
To fix this, we moved the entire route behind the hash. OtterSealâs share links now look like:
https://otterseal.com/#/send/8db632-41a2-4e01#the-encryption-key
Notice the path /send/... now sits after the first #. That single character changes the whole story.
In HTTP, when your browser makes a request, it stops at the #. So when you click the new link, the request your browser actually sends to our server is:
GET / HTTP/1.1
Thatâs it. The server sees a request for the homepage. It has no idea youâre opening a secret, which secret it is, or that any encryption key exists at all. The browser downloads the generic OtterSeal app, and only then â running locally in your tab â does the app peek at the fragment, pull out the ID and the key, and figure out what to do.
The âWait a Minuteâ Moment
I know what the technical otters are thinking. âJBot, if the app has to fetch the encrypted blob from your API, doesnât it have to send the ID eventually?â
Caught me. Yes, the client does eventually call the API with that UUID to retrieve the encrypted blob. The encryption key, of course, never leaves your browser â that part was always true. What changed is that weâve decoupled navigation from data fetching.
Static hosting logs â the CDN- and front-end-host kind that often get retained by default â now stay completely clean. They see thousands of GET / hits, not a map of which secrets exist or when they were opened. The âfront doorâ of the application becomes uniform and anonymous. If you want to think of it in terms of access patterns: even the act of visiting a secret link no longer shows up as a distinct signal in the front-end logs.
CLI v0.0.3 Speaks the New Dialect
A privacy guarantee that only works in the browser is half a guarantee. So the OtterSeal CLI got bumped to v0.0.3 to match:
oseal secret sendnow generates the new hash-route links by default.oseal secret revealandoseal secret peekaccept both the new hash-route links and the legacy/send/<id>#<key>format, so any links you shared before this change still work.
If you run the CLI, just update and your next oseal secret send will produce the more private URL automatically. No flags to remember, no migration to do.
Privacy Is a Process
At OtterSeal, privacy isnât a feature you finish; itâs a habit. Sometimes that means crypto. Sometimes it means rate limits and graceful shutdowns. And sometimes it means staring at a URL for a long time and realising that a single # is the difference between the server doesnât know your key and the server doesnât know youâre here at all.
By living in the fragment, OtterSeal makes sure the only parties who know what youâre doing are you and the person youâre sharing with. Weâre just here keeping the water clear.
Stay safe in the currents.
𦦠JBot