JDK-8268392 : Provide clear run-time warnings about Security Manager deprecation
  • Type: CSR
  • Component: security-libs
  • Sub-Component: java.security
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 17
  • Submitted: 2021-06-08
  • Updated: 2021-07-14
  • Resolved: 2021-06-17
Related Reports
CSR :  
Relates :  
Description
Summary
-------

In connection with [JEP 411](https://openjdk.java.net/jeps/411), provide clear warnings when a Security Manager is enabled at startup or installed at run time. If a command line option prevents a Security Manager from being installed at run time, provide a clear message in the `UnsupportedOperationException` thrown by `System::setSecurityManager`.

Problem
-------

The current warning when a Security Manager is enabled at startup or installed at run time is:
```
WARNING: The Security Manager is deprecated and will be removed in a future release.
```

The current message in the `UnsupportedOperationException` thrown by `System::setSecurityManager` when `-Djava.security.manager=disallow` occurs on the command line is:
```
Runtime configured to disallow security manager
```

Both statements are true, but they provide no context for anyone seeing them. The message when a Security Manager is installed at run time is especially inadequate, since the person who sees it is unlikely to be the author of the code that attempted to install a Security Manager. The message also sows confusion over whether the installation succeeded.

We can improve these warnings to contain more details and to better assist people (such as support engineers) who see them in a production environment.
 
Solution
--------

When the Security Manager is enabled on the command line, we will enhance the warning to indicate that a command line option was involved in enabling the Security Manager, and that the Security Manager will be removed in a future release.

When the Security Manager is installed at run time, we will enhance the warning to show which class called `System::setSecurityManager`. This warning is analogous to the _illegal reflective-access warning_ introduced in Java 9 to show when a class uses reflection to call a method that is otherwise inaccessible. (Illegal reflective-access warnings are described in [JEP 261](https://openjdk.java.net/jeps/261#Relaxed-strong-encapsulation). They appeared in Java 9 through Java 16. Java 17 no longer gives such warnings because it disallows the use of reflection that caused them, as described in [JEP 403](https://openjdk.java.net/jeps/403).)

When a Security Manager is disallowed at run time via `-Djava.security.manager=disallow` on the command line, but a program attempts to install a Security Manager at run time via `System::setSecurityManager`, we will change the detail message of the exception thrown by `System::setSecurityManager` to indicate that the Security Manager is deprecated and will be removed in a future release.

Specification
-------------

(1) If the default Security Manager or a custom Security Manager is enabled at startup:

```
java -Djava.security.manager                    MyApp
java -Djava.security.manager=""                 MyApp
java -Djava.security.manager=default            MyApp
java -Djava.security.manager=com.foo.bar.Server MyApp
```
then the following warning is issued at startup:
```
WARNING: A command line option has enabled the Security Manager
WARNING: The Security Manager is deprecated and will be removed in a future release
```

(The four invocations of `java -D...` shown above set the system property `java.security.manager` to, respectively, the empty string, the empty string, the string `default`, and the class name of a custom Security Manager. These invocations were the supported ways of enabling a Security Manager at startup in Java releases prior to Java 12. Java 12 added support for the strings `allow` and `disallow`, shown next.)

(2) If a Security Manager is not enabled at startup, but could be installed dynamically during run time:

```
java MyApp
java -Djava.security.manager=allow MyApp
```
then no warning is issued at startup. Instead, a warning is issued at run time when `System::setSecurityManager` is invoked, as follows:

```
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by com.foo.bar.Server (file:/tmp/foobarserver/thing.jar)
WARNING: Please consider reporting this to the maintainers of com.foo.bar.Server
WARNING: System::setSecurityManager will be removed in a future release
```

(The second line adopts the approach of the illegal reflective-access warning by loudly identifying the caller's class name and code source (i.e., JAR-file path). It is understood that this will likely cause the second line to wrap.)

(3) If a Security Manager is not enabled at startup, and the system property `java.security.manager` is set to `disallow`:

```
java -Djava.security.manager=disallow MyApp
```
then no warning is issued at startup, nor at run time if an attempt is made to install a Security Manager dynamically by invoking `System::setSecurityManager`. However, every invocation of `System::setSecurityManager` will throw an `UnsupportedOperationException` with the following detail message:

```
The Security Manager is deprecated and will be removed in a future release
```
Comments
Moving to Approved. A suggestion to consider for future refinement: being able to change the configuration to print call-stack information when System::setSecurityManager similar is called.
17-06-2021

I think considering adding JFR events for deprecation notices like this would be a good idea in a future continuation of this effort, warnings in logs are easily overlooked. That being said, I agree with Alan that there are enough ways to identify usages for now.
16-06-2021

As discussed in the javadoc of java.lang.SecurityManager, the system property java.security.manager is an artifact of the JDK implementation, not the Java SE Platform. Therefore, the behavior of the JDK's `java` launcher when a JDK system property is set is a JDK concern, not an SE concern. If the system property is not set at startup, but a Security Manager is installed later via java.lang.System::setSecurityManager, then a warning is emitted by the implementation of setSecurityManager. The existence and content of this warning are not specified by the Java SE Platform.
09-06-2021

The warning message detail is implementation specific so I wouldn't expect the scope to be "SE".
09-06-2021

Is the Scope definitely `SE` or it might be actually closer to `JDK` ?
09-06-2021

Moving to Provisional. Would adding any JFR events be useful here?
09-06-2021

[~dbessono] I think it is a good question, and the scope probably affects both JDK and SE. First, the Security Manager is part of SE, and these changes will also be added to JEP 411, of which the Scope is SE. So on that basis I think the scope should be SE, and also because we ideally want these warnings to be issued by all SE implementations. However, the `java.security.manager` system property (although never clearly specified) is thought to be a JDK-specific property (and is documented as such in the `SecurityManager` API), thus it could be interpreted that the warnings that apply to it are also JDK-specific. [~abuckley] any thoughts here? [~darcy] I had not thought about whether JFR is appropriate but my feeling is that these are more like diagnostic warnings, and less to do with monitoring how the application is behaving.
09-06-2021

JFR tends to be used more for monitoring, health, performance, diagnostics. With jdeprscan for static analysis, and a warning at run-time, then I think we have enough ways to identify usages of the SM for now.
09-06-2021