SQL Server Check

Contained database users

This is one of many SQL Server checks performed by our free sp_Check tools.

Learn More About Our sp_check Tools

Checks Performed

ID
Check
362
Contained database users

What’s the issue?

Partially contained databases allow users to be created and authenticated at the database level rather than through a server-level login. A contained user carries its own password or maps directly to a Windows principal, and the client specifies the database at connection time so SQL Server can authenticate against it without consulting sys.server_principals.

The capability requires the instance-level contained database authentication option to be enabled and the individual database to be set to PARTIAL containment. Once both are in place, anyone with db_owner rights in that database can create authenticated users.

This finding identifies databases containing users that authenticate directly against the database, detected by querying sys.database_principals for user types S and U with authentication_type indicating database-level authentication.

Why is this a problem?

Contained users bypass server-level login controls. Reviewing sys.server_principals no longer gives a complete picture of who can connect to the instance, because contained users reach the same network endpoints and the same engine without appearing in any server-level view.

The permission model also changes for these users. A db_owner in a contained database can create new authenticated principals with strong passwords and broad rights inside that database, without any approval or visibility at the server level. This is a delegation of authority that is typically not intend when granting db_owner.

Server-level policies do not apply either. Login auditing configured at the instance level, server-level logon triggers, and permission denials applied to server principals do not govern contained users in the same way, which can produce gaps in both security controls and audit records.

What should you do about this?

Identify contained users by querying sys.database_principals in each database with containment set to PARTIAL, filtering for users whose authentication type is database-level. Review each user with the application owner to confirm the access is intentional and still required.

Confirm that containment was enabled deliberately. If the requirement no longer exists, migrate the contained users to server-level logins with mapped database users, set the database back with ALTER DATABASE [DatabaseName] SET CONTAINMENT = NONE;, and disable the instance option if no other database needs it.

For databases where containment is genuinely required, tighten db_owner membership since that role controls who can create additional authenticated users and document accordingly.

Type

Security

Importance

Medium

sp_Checks