Deploying Assemblies to BIN Versus GAC

I had a good conversation with a systems engineer recently about where feature assemblies should be installed. I think it’s worth sharing my opinion on this here. His opinion was based on common advice that web part assemblies should go in the BIN folder and include a proper CAS policy. My opinion is based on many years of .Net development and my assessment of what an organization should have in place before introducing the configuration management burdens CAS brings to the table.

The only thing that is inherently special about an assembly in the GAC in .Net is that it can be resolved and loaded based on its full name. The full name includes the public key token and version which are embedded in the assembly. The public key is used against a hash of the assembly (created with a private key) to verify the assembly is not altered. This is why the full name of a signed assembly is called a "strong name". And, this is part of the mechanism used to handle multiple versions of the same assembly.

The public key is the most commonly used evidence for code access security, and as a result, if you are creating a CAS policy for an assembly that is going in the BIN, you probably won’t skip code signing which is a requirement for installing an assembly to the GAC.

.Net gives assemblies in the GAC full trust by default.

Assemblies loaded from the GAC get the same amount of process isolation as assemblies loaded from anywhere else. If ten application domains load the same assembly, there are ten instances of the assembly loaded, not one. Assemblies don’t get loaded until a process in the app domain tries to invoke code in the assembly. So, putting an assembly in the GAC, or even referencing the assembly in an assembly manifest, will not cause the assembly to load or code to run. Putting an assembly in BIN on one site does prevent other sites from loading the assembly because their app domains can’t find the assembly to load it. Putting it in the GAC won’t cause them to load it.

Full trust does not mean that the assembly can do anything that it wants. It has permissions up to those of the identity it is executing under unless it uses impersonation to explicitly assume the identity of a more privileged account. This is a big difference between .Net and native code.

Anyway… In my opinion, the best argument to be made for putting assemblies into BIN instead of the GAC in a SharePoint site is that, assuming the CAS policies are tightly controlled by a group other than development, it requires the devs to explicitly state that the assembly needs to do something out of the norm and could potentially prevent a rogue dev from sneaking in code that is mucking with stuff on the disk, database, registry, etc.

But, this requires governance to affect.

Absent governance an assembly in BIN is no more or less dangerous to the overall stability of the server than an assembly in the GAC. And, in my opinion, if the environment is a farm and if the decision to put an assembly in BIN means that the environment now requires custom policies on a per web app basis, the BIN approach has a significant downside. You could mitigate by deploying policies directly based on a custom evidence, like a corporate-wide public key, but that would only really work if the dev group delay-signed the assemblies and another group completed the signing and built the solution.

But, absent strong and continuing governance and review with clear demarcation between dev and production and mature configuration management practices, putting bits into BIN is more likely to cause problems than simply putting them in the GAC.

So, to sum it up, there are times when CAS policies address clear requirements and in those cases, BIN might well be the way to go. But absent the ability to clearly trace the decision to an actual requirement, I contend that it is not by default ‘better’.

Author: Doug Ware