All About Assert Part III: Dispelling the Myths

So far we've seen What Assert Actually Does, and What Assert Is Good For, now its time to examine some popular misconceptions about the Assert stack modifier.

Myth #1: Assert changes an assembly's permission grant

Assert is a stack walk modifier.  It doesn't modify the permission grant that any assembly has, rather it prevents the stack walk for a permission demand from continuing up the call stack.  Assert is effective because it stops a permission demand from ever reaching assemblies without the given permission.

Myth #2: Assert is just a perf optimization

Assert should never be used as a perf optimization.  Oftentimes, in an attempt to speed up the security system, people think of using Assert to stop the call stack walk.   Doing this completely circumvents the CAS system, and will more than likely lead to a security hole down the line.  It's very unlikely that if your application is having performance problems that stopping a security stack walk early on will solve them, you should instead measure and measure again, then fix the areas that are actually causing the problem.

Myth #3: You don't need the permissions that you're Asserting in order to effectively Assert them

This one is pretty easy to get confused about because of the observed behavior.  When you Assert some permissions, the code doing the Assert needs to be granted the following two things:

  1. SecurityPermission with SecurityPermissionFlag.Assertion set.  If this is not true, calling Assert will result in a SecurityException.
  2. The permissions being asserted.  If this is not true, there's no observable runtime behavior difference (causing the confusion that leads to this myth).  The call to Assert will return as if the assertion were set, however when a subsequent demand occurs, the Assert will not stop the stack walk.

Myth #4: Assert will last for the lifetime of the process

Since Assert is a stack walk modifier, it is only in effect while the method that called Assert is still on the call stack.  Once this method returns and its frame is popped, the Assert is no longer in effect.

Myth #5: Since Assert goes away at the end of the calling method, I never need to call RevertAssert

While this is technically not a myth, and is true, good coding practice is to always Assert immediately before calling whatever method will result in the permission demand, and call RevertAssert as soon as you don't need the elevated permissions any more.  This limits the window of time that malicious code could use to take advantage of the stack walk modifier.

Myth #6: Assert stops all stack walks from proceeding further up the call stack

This is probably the most common misconception I see about Assert.  Asserting a set of permissions will only prevent a stack walk for those permissions from going further up the call stack.  For instance, if I assert FileIOPermission, and code I call demands RegistryPermission, that stack walk will blow right by my Assert and head further up the call stack.

A more interesting scenario occurs when a demand occurs that is a superset of the set of permissions that I've Asserted.  For instance, if I Assert FileIOPermission, but some code I call demands a permission set containing both FileIO and Registry permission.  Clearly stopping at my Assert would be the wrong behavior, but so would continuing past it.  In this case, when the CLR hits the Assert it will remove any permissions being Asserted from the permission set being demanded, and send the remaining permissions further on the stack walk.

Myth #7: Asserting a permission means that a demand for that permission will always succeed

I've already covered three cases where an Assert will not prevent a SecurityException (Myths #3, 4, and 6).  There are at least two other ways that this can happen.  Can you figure them out?  Post your guesses in the comments, and I'll provide answers in tomorrow's post.