Flow
Four role actions and the check on each
1List
Points at nothing. The super-admin role is dropped from the reply.
2Create
Points by new name. The name is trimmed, lowercased and compared.
3Update
Points by id and new name. Both the new name and the stored name are checked.
4Delete
Points by id. The stored name is looked up and checked.
Any company admin in my staff scheduling app could pull up the role list and see the super-admin role in it. They could also save over it or delete it.
One gate, no row check
That day I let company admins into parts of the admin API, so each company could run its own stores, users and roles. The roles endpoint had one gate: are you an admin of this company, or a super admin? Past that, it did whatever the request asked.
That gate checks who may use the endpoint. It never checks which rows you may touch. One row in that table isn't any company admin's business.
I'd bet on a mess rather than a takeover, but I haven't checked how much harm an edit to it could have done. Super-admin status rides on a flag in the login token, and setup hands the role to the first account by name.
A check for each action
Each action points at a role in its own way, so each got its own check for anyone who isn't a super admin:
- Listing drops the protected role from what comes back.
- Creating compares the new name, trimmed and lowercased, to the protected one.
- Updating checks the new name and also looks up the name already stored for that id.
- Deleting does that same lookup.
The lookup is the part I'd have missed. Without it, someone could take the protected role's id and rename it to something dull, and the request would look fine.
A refusal looks like any other "forbidden" answer. Super admins see no change, and the admin docs now say the built-in role is hidden from company admins.
Plain text, no test
New names are cleaned up before the compare, but the stored name isn't. If that row is ever saved with odd spacing or capitals, the id lookup stops matching.
The protected name is plain text typed into each check, and there's no test yet. A deliberate rename by a super admin would switch every one of those checks off.
When company admins save a user, they can only add roles from a short fixed list of store roles, so they can't hand out the protected one that way. That's the only other door I've checked.