Flow
Rules for picking the organization
1Bad or missing login
Answer with a 401. A token with no organization gets one too.
2Dev mode
A flag you turn on by name, listening only on your own machine.
3CORS
Allow only the callers you expect.
4Tool helper
No default. No organization means an error.
5Tool inputs
Never ask the model for an organization.
6Tests
Start with failures: no token, bad token, empty environment.
Committed: a server that lets an AI assistant read recorded coding sessions. If you deploy it the way its README says, it can answer a bad token with one organization's data.
One big commit
It was one big commit: six read-only tools, an auth module, a shared package and long setup guides. I suspect an agent wrote most of it. I committed it, so it's mine. The only test checks nothing.
The queries filter by organization
Every query filters by organization, and the value is passed in safely. The database side is fine. The trouble is in the code that picks the organization.
Three ways in, no way out
The server tries three things in order: a login token, a dev header that needs a flag, and a default organization from the environment. The default is used when the mode isn't set to production.
if (claims) return claims; // bad token? keep going
if (env.FALLBACK_TEAM && env.APP_MODE !== "live") return fallback();
A bad token doesn't stop the request. It just moves on. So a fake token, an old token and no token all reach the default. And "not production" is also true when nobody set the mode at all.
The token checker makes it worse. A real token with no organization in it gets dropped, and the request lands in the default organization anyway.
The second default
The helper that runs each tool also falls back to the default when no organization came in. It only refuses if no default is set.
The README walks you straight into it
Every hosting recipe in the README sets a default organization. None of them sets the mode to production. Unless the host sets the mode on its own, follow one exactly and anyone on the internet can read that organization's sessions.
Wildcard CORS and the loopback idea
The server lets any website call it. So even a dev copy on your own machine might be readable from a page in your browser. Keeping dev mode on your own machine isn't enough by itself.
Two authenticators, and the server picked the loose one
The auth module had a stricter checker with no default. The server wrote its own looser one and used that. If you review the strict one, you'll think the system is safe.
The shared package trusts a header
The shared package takes the organization from a header anyone can set. One tool also asks the model to fill in the organization, which teaches it the caller gets to choose.
The shape I want instead
If you're building something like this, these are the rules I'd hold it to:
- A failed or missing login is a 401. A token without an organization is a 401 too.
- Dev mode is a flag you turn on by name, and it only listens on your own machine.
- Only the callers you expect are allowed by CORS.
- The tool helper has no default. No organization means an error.
- No tool asks the model for an organization.
- There's one auth function, not two.
- Tests start with the failures: no token, bad token, empty environment.
What the code can't tell me
Fallback logins do print a warning, so a log would show one. Whether a copy ever ran in public, though, is not something the code can tell me.