What’s the issue?
CLR assemblies registered in a database carry a permission set of SAFE, EXTERNAL_ACCESS, or UNSAFE. The two elevated sets allow managed code to reach outside the database engine, including file system access, network calls, and in the case of UNSAFE, unrestricted operations including calls into unmanaged code.
An assembly can be authorized either by signing it with a certificate or asymmetric key that has been granted the corresponding permission in master, or by relying on the older trust model based on the TRUSTWORTHY database property and the privilege level of the database owner. Signing is the controlled path; the trust model is the one that produces escalation.
This check identifies unsigned assemblies with an elevated permission set in a database where an escalation path exists. The path is evaluated per database as one of three conditions: the database is TRUSTWORTHY and owned by a sysadmin, the database is TRUSTWORTHY, or the database is owned by a sysadmin.
Why is this a problem?
When a database is TRUSTWORTHY and owned by a sysadmin, the combination is the most direct escalation path in SQL Server. Code in an elevated assembly executes with the owner’s authority and the instance trusts the database to make that assertion outside its own boundary, so anyone who can register or invoke the assembly effectively operates with full instance control.
TRUSTWORTHY alone still removes the boundary that normally confines database code, allowing the assembly to act across databases and at the server level using whatever authority the owner holds. A sysadmin owner alone provides the elevated authority without the cross-boundary trust, which still gives db_owner members a path to create and run code with sysadmin-level permissions inside a wide scope.
Because the assembly is unsigned, there is no certificate tying its authorization to a controlled key. Anyone with sufficient rights in the database can replace or add assemblies and inherit the same escalation, with no signing step to gate the change and no certificate ownership to review.
What should you do about this?
Identify the affected assemblies by querying sys.assemblies for those with permission_set_desc of EXTERNAL_ACCESS or UNSAFE, and check sys.assembly_files and the assembly’s signing state to confirm it is unsigned. Capture the escalation reason for each database, since it determines which remediation applies.
Address the escalation path first, as this closes the exposure regardless of the assembly. Set TRUSTWORTHY off with ALTER DATABASE [DatabaseName] SET TRUSTWORTHY OFF; where it is not required, and reassign the database to a dedicated low-permission owner with ALTER AUTHORIZATION ON DATABASE::[DatabaseName] TO [OwnerLogin];.
Then move the assemblies to a controlled authorization model. Sign each one with a certificate, create a login from that certificate in master, and grant it UNSAFE ASSEMBLY or EXTERNAL ACCESS ASSEMBLY as appropriate, or add the assembly hash with sp_add_trusted_assembly. Drop any assemblies that are no longer used rather than leaving them registered.