Skip to content

@omit can be bypassed by explicit select #2671

@Azzerty23

Description

@Azzerty23

Description

Fields marked with @omit are correctly stripped from query results in the default case, but an explicit select on the omitted field bypasses the protection and returns the field's value.

This defeats the security guarantee of @omit, which is most commonly used for sensitive fields like password hashes.

Example

model User {
  id           String @id @default(cuid())
  email        String @unique
  passwordHash String @omit
}
// ✅ Works as expected — passwordHash is omitted
await db.user.findFirst({ where: { email } });
// => { id, email }

// ❌ Bypasses @omit — passwordHash is returned
await db.user.findFirst({
  where: { email },
  select: { passwordHash: true },
});
// => { passwordHash: "$2a$12$..." }

Reproduction

https://stackblitz.com/~/github.com/Azzerty23/v3-doc-quick-start/tree/Azzerty23/zenstack-omit-issue

Expected behavior

@omit should be enforced regardless of how the field is requested. An explicit select (or include) targeting an omitted field should either:

  • silently strip the field from the result, or
  • throw a validation error at query time.

Actual behavior

The explicit select takes precedence and the omitted field is returned.

Environment

  • ZenStack version: 3.7.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions