JEP proposed to target JDK 17: 411: Deprecate the Security Manager for Removal
sean.mullan at oracle.com
Mon May 24 15:29:11 UTC 2021
Comments inline ...
On 5/22/21 10:11 AM, David Lloyd wrote:
> On Fri, May 21, 2021 at 6:04 PM <mark.reinhold at oracle.com> wrote:
>> The following JEP is proposed to target JDK 17:
>> 411: Deprecate the Security Manager for Removal
> I'm not a committer or reviewer, so perhaps my feedback is unwelcome - but
> one can't help but note the amount of heated discussion on this topic, and
> the determination of whether or not the problematic points have been
> addressed satisfactorily is probably pretty subjective. I have a bit of
> experience in this area, having either designed or having had a major part
> of the design of the authentication and authorization APIs presently in use
> in WildFly , as well as the WildFly security manager  (and a
> significant number of other security-related APIs), so I thought I'd give
> some feedback and also offer a possible compromise.
> The security manager defines a variety of behaviors. Some of these have
> clearly been supplanted by other APIs (like getClassContext() vs
> StackWalker) or security mechanisms (checkPackageAccess() and friends vs
> the new encapsulation protections). There are also however other APIs on
> the security manager which clearly have no replacement. These include
> socket and file access checking APIs, and of course the general permission
> check methods. In addition, the JEP proposes deprecation of the access
> controller and policy classes which are the mechanism of stack-based access
> checking, and finally unavoidably bumps against JAAS, which itself is a
> very difficult and problematic API which also uses the same stack-based
> access mechanism (and which we here at Red Hat have for the most part long
> since abandoned).
Has Red Hat mostly abandoned JAAS entirely or more specifically the
stack-based JAAS authorization mechanism that depends on the Security
Manager? I'm just curious why this proposal is important to you - is it
on behalf of Red Hat or just your personal preferences?
> A large part of this deprecated machinery relates to the stack-based access
> controller (not to mention, I believe, a nontrivial number of CVEs). The
> idea, of course, was that one can authenticate untrusted or semi-trusted
> code. It is definitely clear through years of experience on all sides
> though that one cannot truly rely on this mechanism to protect against
> malicious code; it is as easy as an infinite loop to cause massive
> undesired CPU usage (and, in this modern $/cpu world, cost) for example.
> However, one other undeniably useful function of the security manager is to
> authorize basic native operations *not* in the context of what code is
> executing, but what person or principal is executing it. In other words,
> the use case of *trusted* code running on behalf of one of many potentially
> untrusted users - probably the widest application of server-side Java in
> existence today. It cannot be argued that removing all of the above
> security checks does not weaken security of such users, when they could
> have a narrower authorization applied to them to limit the possibility of
> impact of server exploitation.
But I assume that in these cases, it is due to a vulnerability in some
trusted code that the user exploited or a weakness in some higher level
authorization mechanism that the user was able to subvert.
In practice, I don't think the Security Manager can or should take the
place of a user-based Authorization provider. It is too low-level and
too difficult to use and deploy, for the reasons mentioned in the JEP.
But I think you agree with a lot of that anyway.
> On the other hand, the cost of the SecurityManager mechanism as it stands
> is undeniably too high; there is absolutely no point in arguing
> otherwise, in my view. Leaving aside the substantial CVE load, the access
> controller and policy APIs are very difficult to use correctly by
> containers and frameworks, for one thing, and are cumbersome for users as
> well. Many users and frameworks get doPrivileged() wrong, and combining
> JAAS subjects into the same mechanism historically doesn't even work
> consistently between otherwise-compliant JDK implementations.
> What I would propose then is a compromise aimed at maximizing the amount of
> value retained and minimizing the amount of cost incurred, by *only*
> retaining permission checks that specifically pertain to or are useful for
> user authorization, while *also* deprecating (for removal) the existing
> problem-prone stack-based access checking mechanism, policy, and security
> manager implementation.
> Thus I would suggest not deprecating all of SecurityManager, rather just
> the following:
> * java.lang.SecurityManager#getClassContext - it is replaced by StackWalker
> * java.lang.SecurityManager#getSecurityContext
> * java.lang.SecurityManager#checkCreateClassLoader
> * java.lang.SecurityManager#checkPermission(java.security.Permission,
> java.lang.Object) - the overload which accepts a "security context"
> * java.lang.SecurityManager#checkPackageAccess
> * java.lang.SecurityManager#checkPackageDefinition
> * java.lang.SecurityManager#checkSecurityAccess
> * java.lang.SecurityManager#getThreadGroup
> ...as well as their dependent methods and security checks. These checks
> generally pertain to determining whether the application or its frameworks
> are trusted to perform certain operations, but are far less useful for user
> authorization, as far as I can determine. I would probably even include
> the system property access methods as well - though I saw Peter arguing
> that those in particular were useful, I have my doubts, but that could
> obviously be worked out.
Right, and I think this becomes a slipperly slope and would result in
long and endless debates about which permissions people think are
important. What about RuntimePermission "exitVM.*"? That is typically
not an issue for server applications, but if you include that, then one
could say that is useful for sandboxing against untrusted code so why
not RuntimePermission "createClassLoader", and all the other permissions?
I think it is better to make a clean break from it.
> Further I would recommend the following change: make
> java.lang.SecurityManager#checkPermission(java.security.Permission) either
> a no-op or throw UnsupportedOperationException. Ideally, SecurityManager
> and checkPermission() would be made abstract (and, for completeness, the
> SecurityManager constructor); perhaps after the deprecation period, such a
> change could be made. It's a bit tricky here, because the deprecation
> policy doesn't seem to cover the case of making a concrete class or method
> The remaining proposal would need slight modification in certain ways: for
> example, the security manager allow/forbid flags would still make sense and
> need to be retained, and the permission checks in socket and file system
> code would need to be retained.
> After this change, SecurityManager would be decoupled from the stack-based
> access controller. This means that any implementation of authorization
> would be the responsibility of third-party libraries. The remaining JDK
> authorization checks would then be easily testable - much more so than
> today, because the contract becomes substantially simpler in the absence of
> AccessController - and still usable by third party security managers to
> perform user authorization checks on these native operations. And, it would
> still be possible for third parties to provide stack-based access control
> checks using StackWalker for an extra level of security with absolutely
> zero additional cost to JDK maintenance (and the burden of coping with the
> lack of doPrivileged would reside squarely on the third party).
> As for JAAS, nobody would be happier than us to see it just go away, though
> that may be beyond the scope of this change. The proposed scope locals
> give what is potentially a very good opportunity to employ a vastly
> superior means of propagating security context between tasks. Under this
> proposal, a third-party security manager which uses a scope local security
> context for authorization would not only be a useful and measurable
> security improvement over an "unsecured" JDK, but would also likely be
> substantially more performant (and, if I may say so, reliable) than
> anything using JAAS today. It should even be possible, in the future, to
> standardize on a new authentication and authorization identity propagation
> API using these mechanisms - at least in Jakarta EE and/or MicroProfile, if
> not in the JDK itself.
Note that we have already filed two follow-on issues to enhance JAAS and
decouple it from the Security Manager:
> Essentially what I propose is only slightly departed from the current JEP
> 411 proposal, by introducing the exception of retaining certain permission
> checks and the security manager class itself.
> Please give this compromise some consideration. Thanks!
I think if we are to consider this path (and that is something that
would involve more discussion), it would be much cleaner to define a
completely new API, say "ResourceManager" and make a clean break from
the Security Manager. I think this idea can be explored more in later
JDK releases to see if there is merit to this approach. I think it would
be much harder, and confusing to keep the Security Manager around but
for a much more limited functionality, and decide which permissions are
ok, which are not, etc. We would have to define what is the "old" vs
"new" Security Manager.
Let's move Java forward rather than keeping one foot in the past.
>  https://github.com/wildfly-security/wildfly-elytron
>  originally:
> - which is now:
More information about the jdk-dev