In terms of class/member access I would say "security" is more about API security. When you publish code that is fairly open, others may end up using your code in ways you did not intend, that make it harder for you to make internal, non-breaking changes in the future.
While some of the choices you make in OOP class/member access may influence your overall system security from external attacks, those choices are not strongly related to security from those type of attacks. Once you are already sharing program execution space, in most cases the other program can really do almost anything it wants to do, in some way or other. (For example,
private members in Java can be accessed through reflection quite easily via
When developing APIs, those kind of hacks are never supported by the library author, so they are "use at your own risk". With a good field/class access strategy, APIs can be refactored extensively with few external API breakages.
I tracked down the article that you are referring to, and the context helps illuminate this issue.
Point three is actually related to my original answer above:
3) Compatible. If in the future I discover that I should have sealed a class, I'm stuck. Sealing a class is a breaking change. If I discover that I should have left a class unsealed, unsealing in a future version is a non-breaking change. Sealing classes helps maintain compatibility.
The next bullet point is your original quote:
4) Secure. the whole point of polymorphism is that you can pass around objects that look like Animals but are in fact Giraffes. There are potential security issues here.
Following on helps illuminate the problems that Eric is referring to:
Every time you implement a method which takes an instance of an unsealed type, you MUST write that method to be robust in the face of potentially hostile instances of that type. You cannot rely upon any invariants which you know to be true of YOUR implementations, because some hostile web page might subclass your implementation, override the virtual methods to do stuff that messes up your logic, and passes it in. Every time I seal a class, I can write methods that use that class with the confidence that I know what that class does.
In this case, Eric is clearly referring to cases when a potentially hostile system is actually able to interact with your system with code. In that case, polymorphism does become an issue, since, as Eric says, when you make calls on the objects that are passed in, the object could be doing something you completely didn't intend it to do.
Sealing classes means that the object that is passed in cannot be subclassed in that way. Obviously there would be no need for this if your system is never going to interact with potentially hostile API callers. As my original answer said — often that is such a difficult security risk to manage in and of itself that is simply disallowed altogether.