There are several common misconceptions about the Assert stack modifier, not the least of which are:
Lets take a quick look at what Assert actually does, before addressing these misconceptions. Asserting a permission or permission set is your method's way of saying that it vouches for every method that is calling into it; that the stack walk should go no further.
Looking at an example might make things a little more clear. Lets say I have a shared assembly, Pi.dll, which lives in the GAC and will get FullTrust. Pi.dll contains one class, Pi, which has a Value property that exposes the value of Pi to one million digits. Obviously this is an expensive calculation, so as a performance optimization, I write the calculated value out to %TEMP%\pi.txt, and use this cached value as long as its available.
Now, I write an application that sits on my web site, and calculates the area of a circle. It requires that the Pi library exist on the user's machine, and uses the very accurate Pi value in order to provide accurate results of its own. However, since the application runs from the Internet it does not get very many permissions, and certainly doesn't have Environment permission to read %TEMP% or File IO permission to read from and write to %TEMP%\pi.txt.
When calling into my Pi class, the call stack looks like this:
Call Stack Grant Requires ================================================================== mscorlib.dll!System.IO.File::.ctor() FullTrust FileIO Pi.dll!Pi::GetCachedValue() FullTrust Environment, FileIO Pi.dll!Pi::get_Value() FullTrust Execution CircleCalc.exe!CircleCalc::Main() Internet Execution
Now, when the File constructor does its demand for FileIOPermission, its going to find that Pi::GetCachedValue has this permission, and Pi::get_Value also has this permission. Then it will hit CircleCalc::Main() and find that the Internet permission set does not contain FileIO permission, causing a SecurityException.
Since GetCachedValue is only opening a very specific file, and does not allow the calling code arbitrary access to the file system, file's contents, or environment, and since I've done a full security review on its code, I've decided to enable this scenario. I can do that by calling Assert() for Environment and FileIO permission in GetCachedValue(), which will create a situation like the following:
Call Stack Grant Requires ================================================================== mscorlib.dll!System.IO.File::.ctor() FullTrust FileIO Pi.dll!Pi::GetCachedValue() FullTrust Environment, FileIO--------------------Assert(Environment, FileIO)------------------- Pi.dll!Pi::get_Value() FullTrust Execution CircleCalc.exe!CircleCalc::Main() Internet Execution
Now, when the File constructor demands FileIO permission it is going to check GetCachedValue(), find that it has permission, then hit the wall that the Assert put up, and goes no further up the stack. Since everything checked so far has enough trust, the demand succeeds, and my untrusted application has caused a file on the local disk to be read.
Obviously this can be very dangerous, and only code that has been very carefully looked at should call Assert. For instance, if in the example above there was a utility method SetCacheFile(string path), where the user could set the cache file, and the return value of Pi::Value was simply the bytes contained in that file, this code would be horribly unsafe.
In order to reduce the risk of a malicious caller being able to take advantage of the fact that your code is going to Assert permissions, one of the easiest things to do is not Assert until just before you need to use the given permission, and always RevertAssert immediately after you are done with the asserted permissions.