JEP proposed to target JDK 17: 411: Deprecate the Security Manager for Removal

David Lloyd david.lloyd at
Sat May 22 14:11:32 UTC 2021

On Fri, May 21, 2021 at 6:04 PM <mark.reinhold at> 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 [1], as well as the WildFly security manager [2] (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).

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.

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.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 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.

Further I would recommend the following change: make
java.lang.SecurityManager#checkPermission( 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.

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!

[2] originally:
     - which is now:
- DML • he/him

More information about the jdk-dev mailing list