(WEB_PORTAL) Blocking Admin Privilege Escalation at the API Level
Overview
As a follow-up to introducing the three-tier permission system, we went back and verified — at the API level this time — that each permission tier truly couldn't encroach on another. Hiding a button in the UI isn't enough; the principle we wanted to uphold was that real security means every API request is validated on the server itself.
Key Implementation Points
1. Blocking Privilege Escalation Attempts
The structure allowed a regular admin to include a role value when registering a new person, and if that value were trusted as-is, an admin could theoretically promote themselves or someone else to super admin. To prevent this, whenever a regular admin submits a creation request, the server now unconditionally overwrites the role value with the default (regular employee).
2. Protecting Higher-Privilege Accounts
Requests from a regular admin to modify or delete a super admin account, or to change a role value directly, are now explicitly rejected on the server.
Requester = admin, target = super_admin account → reject update/delete
Requester = admin, request body includes a role change → reject
3. Separating Role-Change Into a Dedicated API
Rather than folding role-changing functionality into the existing personnel management API, we split it out into a separate API accessible only to super admins. We also blocked users from changing their own role, which prevents accidental self-demotion or account lockout as a side effect.
Retrospective
- We reconfirmed that "it's safe because the button isn't visible in the UI" is a false assumption from a security standpoint. No matter how well the UI hides an action on the client, a request can always be sent directly, so real enforcement always has to be the server-side validation as the final authority.
- For permission-related logic, rather than piling more conditionals onto a general-purpose API, splitting sensitive actions into their own dedicated API made the rule — "only this role may call this endpoint" — much clearer, and that clarity reduced the chance of mistakes.