T09 · Insecure Skill Coding Practices
- Location
references/security-and-multitenancy.md:173- Finding
Tenant Isolation Is Not Enforced by Database Foreign Keys
- Content
View full analysis
Vulnerability Details
File Location:
references/security-and-multitenancy.md, lines 173–175
Vulnerability Type: Cross-tenant referential-integrity weakness
Risk Level: Highmarkdown 4. **Foreign keys should stay within a tenant.** Add application-level checks to ensure cross-table references share the same `tenant_id`.Technical Analysis
The shared-database multi-tenancy guidance relies on application-level checks to ensure that related records have the same
tenant_id. Independent foreign keys referencing only an entity ID do not enforce this security invariant at the database layer.For example, if a child table contains both
tenant_idandaccount_id, but its foreign key references onlyaccounts.id, MySQL can accept a child row belonging to tenant A whoseaccount_ididentifies an account belonging to tenant B. Application-level validation alone is vulnerable to omitted checks, defective import jobs, administrative scripts, compromised application paths, and direct database writes.Tenant isolation is a security boundary and should therefore be enforced through composite database constraints rather than treated solely as application validation.
Attack Path
- An attacker authenticates as a user of tenant A.
- The attacker discovers or guesses an entity identifier belonging to tenant B, such as an account ID.
- The attacker submits a create or update request that associates a tenant-A record with the tenant-B identifier.
- The affected request handler, bulk import, integration, or administrative path omits the application-level tenant consistency check.
- MySQL accepts the relationship because the foreign key validates only the entity ID and not the corresponding
tenant_id. - Subsequent joins, reports, activity timelines, updates, or exports may disclose or manipulate data associated with tenant B.
Exploitation requires a write path that accepts a foreign identifier witho ...[truncated 1065 chars]
- Remediation
View remediation
Remediation Suggestions
Enforce tenant consistency directly in the database:
-
Add a composite candidate key to every tenant-owned parent table:
sql ALTER TABLE `accounts` ADD UNIQUE INDEX `uq_accounts_tenant_id_id` (`tenant_id`, `id`); -
Replace single-column foreign keys with composite foreign keys that include
tenant_id:sql ALTER TABLE `contacts` ADD CONSTRAINT `fk_contacts_tenant_account` FOREIGN KEY (`tenant_id`, `account_id`) REFERENCES `accounts` (`tenant_id`, `id`) ON DELETE SET NULL;If
account_idis nullable andON DELETE SET NULLis required, review whether both columns should be cleared; sharedtenant_idgenerally must not be nulled. An alternative deletion policy or schema arrangement may therefore be necessary. -
Include
tenant_idin every tenant-owned junction table, polymorphic association, unique constraint, and relevant index. -
Retain application-level authorization checks as defense in depth. Resolve the tenant from trusted authentication context rather than accepting it from request parameters.
-
Ensure background jobs, bulk imports, migrations, integrations, and administrative tools apply the same tenant restrictions.
-
Add negative integration tests proving that inserts and updates containing cross-tenant references are rejected by MySQL.
-
Audit existing data for mismatched tenant relationships before enabling composite constraints, then correct or quarantine inconsistent records.
-
