Invental/Review lessons/Trust boundaries the server must hold

Trust boundaries the server must hold

A POST that exports data is still a read

Don't derive the permission action from the HTTP verb: a POST that exports data is a read. Pass the action explicitly at every route that doesn't follow REST.

01 · Before and afterThe pattern

TypeScript
// before: guard infers action from req.method → POST means "create"
router.post('/export/:resource', guard(), handler);
// after: the route says what it does
router.post('/export/:resource', guard('read'), handler);
router.post('/sort/:resource',   guard('update'), handler);
// and never assume list order after merging permissions
if (allowed.includes('*')) allowed = allFields;

02 · Run it on your appThe check

Do any of your non-CRUD POST routes (export, search, preview) run permission checks as if they were creates?

If the honest answer is no or not sure, this is worth a look before it reaches production.

Want this checked on your code?

Tell us what you are building and what worries you. We match a senior reviewer to your code and confirm scope before anything starts.

— Get in touch
hi@invental.co ↗
— Or
— What to include

A link or short description of the code or system, what you want checked, your stack, and when you need the answer. No repository access is needed until scope is agreed.

— Or leave a note
We reply within one business day.