IDOR Protection with Zen Firewall

IDOR stands for Insecure Direct Object Reference. It is a class of access control bugs where one account can access another account’s data because a database query is not properly scoped.

In multi tenant SaaS applications, data is usually separated with a column such as tenant_id, account_id, or organization_id. If a query forgets to filter on that column, or uses the wrong value, data can leak across accounts.

IDOR Protection on Zen Firewall analyzes SQL queries at runtime and enforces tenant scoping automatically. If a query is unsafe, Zen throws an error immediately.

This helps you catch multi tenant isolation bugs during development and testing, not after a production incident.

For a deeper explanation of the vulnerability itself, see the blog post: IDOR Vulnerabilities Explainedarrow-up-right

What Zen protects against

When enabled, Zen validates that every relevant query:

  • Filters on the correct tenant column for SELECT, UPDATE, and DELETE

  • Uses the correct tenant ID value

  • Includes the tenant column in every INSERT

  • Sets the tenant column to the correct tenant ID in INSERT

Examples of issues Zen blocks:

  • A SELECT without a tenant filter, allowing one account to read another account’s data

  • An UPDATE or DELETE without tenant scoping

  • An INSERT that omits the tenant column

  • An INSERT that sets the wrong tenant ID

circle-exclamation

How it works

Zen instruments supported database drivers and inspects SQL queries at runtime. For each request, you set the active tenant ID. Zen then verifies that all relevant queries:

  1. Reference the configured tenant column.

  2. Use the same tenant ID that was set for the request.

If a query does not meet these conditions, Zen throws an error and prevents it from executing.

Setup

1

Enable IDOR protection at startup

Enable IDOR protection when your application starts

Configuration options:

  • tenantColumnName

    The column that identifies the tenant in your tables, for example tenant_id, account_id, or organization_id.

  • excludedTables

    Tables that should not be checked because they are not scoped to a single tenant. For example, a shared users table that contains users across all tenants.

2

Set the tenant ID per request

Every request must have a tenant ID when IDOR protection is enabled.

Call setTenantId early in your request lifecycle, typically in middleware after authentication.

circle-exclamation
3

Bypass IDOR checks for specific queries

Some queries are intentionally global, for example cross tenant analytics or internal admin reports.

To skip IDOR checks for a specific block of code, use withoutIdorProtection:

Only queries executed inside the callback are excluded from IDOR validation.

Use this carefully and only where cross tenant access is explicitly required.

Troubleshooting

Missing tenant filter

Your query does not filter on the configured tenant column. This applies to SELECT, UPDATE, and DELETE.

Example:

Add a condition that filters on tenant_id.

Wrong tenant ID value

The query filters on the tenant column, but the value does not match the tenant ID set via setTenantId.

Ensure that all queries use the tenant ID from the current request context.

Missing tenant column in INSERT

Every INSERT must include the tenant column.

Wrong tenant ID in INSERT

The INSERT includes the tenant column, but the value does not match the active tenant ID.

Missing `setTenantId` call

Ensure setTenantId is called for every request before any database queries run.

Supported databases

Currently supported drivers:

  • MySQL via mysql and mysql2

  • PostgreSQL via pg

Any ORM or query builder that uses these drivers under the hood is supported, for example Drizzle, Knex, Sequelize, and TypeORM.

ORMs that use their own query engine, such as Prisma, are not supported unless configured to use a supported driver adapter.

circle-info

If you use ESM, review the ESM caveatsarrow-up-right. Queries inside uninstrumented ESM sub dependencies cannot be checked by Zen.

Limitations

Statements that are always allowed

Zen only checks statements that read or modify row data:

  • SELECT

  • INSERT

  • UPDATE

  • DELETE

The following are recognized and never trigger IDOR errors:

  • DDL statements such as CREATE TABLE, ALTER TABLE, DROP TABLE

  • Session commands such as SET, SHOW

  • Transaction statements such as BEGIN, COMMIT, ROLLBACK

Last updated

Was this helpful?