One thing that I learned while working with .NET (and with some people who quickly switch to a hacking solution) is that if nothing else, reflection often allows people to pass on your โdefensesโ.
Interfaces are not iron programming shackles, they promise that your code will do any other code saying, "I can definitely do this." If you โcheatโ and throw the interface object into some other object, because you, the programmer, know something that is not in the program, then you are breaking this contract. The consequence is lower maintainability and confidence that no one has ever messed up anything in this execution chain, so that any other object is not sent down, which is not displayed correctly.
Other tricks, such as doing read-only things or hiding the actual list behind the shell, are just spaces. You can easily dig into the type using reflection to pull out a private list if you really wanted to. And I think that there are attributes that you can apply to types so that people do not reflect in them.
Similarly, read-only lists are actually. I could probably figure out a way to modify the list itself. And I can almost certainly change the items in the list. So readonly is not enough, nor is it a copy or an array. You need a deep copy (clone) of the source list in order to protect the data to some extent.
But the real question is: why are you fighting so hard with the contract you wrote. Sometimes ad hacking is a convenient way to work around a problem when some other library is poorly designed and does not reveal what it needs (or an error requires you to start digging to fix it.) But when you control the interface and the consumer interface, there are no excuses for not making the open interface as reliable as you need to get your work done.
In short: If you need a list, do not return IEnumerable, return the list. If you have IEnumerable, but you really need a list, then it is safer to make a new list from this IEnum and use it. There are very few reasons (and even fewer, maybe not, good reasons) to refuse the type simply because "I know that this is really a list, so it will work."
Yes, you can take steps to try to stop people from doing this, but 1) the more you fight people who insist on breaking the system, the harder they will try to break it, and 2) they only look for more rope, and ultimately they will end up with enough to hang themselves.