Always authorize on an object loaded from the DB, not on user input
Load the resource from the DB and authorize against it — never trust IDs from the request body alone.
NestJS·Auth & Security·High·Since 2026-05-01
nestjs-security-authorize-from-db-object
Why it matters
| Stake | If ignored |
|---|---|
| Data leak |
|
How to fix
The user sends siteId. You don't authorize on the ID — you load the site and authorize on the loaded object. If it doesn't exist — NotFoundException. Only then check whether the user may act on it.
Examples
Bad
ts
async deleteSite(siteId: string, user: User) {
if (!user.canDeleteSites) throw new ForbiddenException(); // ← generic permission
await this.repo.delete(siteId); // ← deletes any site
}Good
ts
async deleteSite(siteId: string, user: User) {
const site = await this.repo.findById(siteId);
if (!site) throw new NotFoundException();
if (!this.policy.canDelete(user, site)) throw new ForbiddenException();
await this.repo.delete(siteId);
}