These days, many people are using SharePoint anonymously or creating mash-ups of data from various SharePoint sources. As a result, these various resources have differing permissions governing their visibility. For example, the Managed Metadata Term Store cannot be accessed anonymously.
Indeed, the most likely occurrence, and where I discovered this problem, is when you want to display all items in a list even if the current user doesn’t have permissions to edit or view the item. My specific situation was for an editor that needs to know a particular topic exists but doesn’t have the permission to see or edit the topic.
Displaying content from a secure source on a site must be done after the user has logged in or (more likely) via SPSecurity.RunWithElevatedPrivileges. This was the only solution in my case.
Once inside the RunWithElevatedPrivileges security delegate, it’s well known that you must recreate any object that you need to access with full permissions. This is because previously created objects maintain their security context once inside the security delegate. So an SPSite created outside of the delegate will have the same permissions as it does inside the delegate. Although not necessarily straightforward, it’s intuitive that permissions would not get remapped within the delegate.
Slightly less intuitive, and poorly documented, is the fact that the security context for objects created within the security delegate is maintained once you leave the delegate. So if you get a reference to an SPListItem within the security delegate and pass it outside of the delegate, you will still have full control on the item because it was referenced from within the security delegate!
This behavior can lead to some interesting ramifications. In my case, the use of the DoesUserHavePermissions method on the SPListItem class was acting strangely. Calling this method on the item I got out of a security delegate always returned true because the security context followed the object. To avoid this unfortunate situation, I had to get a reference to the item outside of the security delegate to get the correct permissions for the object.
In general, treat SPSecurity.RunWithElevatedPrivileges as a separate context entirely and don’t reuse objects across the context boundary for items with permissions.