I have a Java 8 application that evaluates user provided code via the Nashorn JavaScript ScriptEngine. To provide protection from evaluating malicious code, I am enabling the Java SecurityManager with the following policy:
grant codeBase "file:/-" {
permission java.security.AllPermission;
};
grant {
permission java.net.SocketPermission "*", "accept,connect,resolve";
};
This allows my main Java application to run unrestricted but any JavaScript code is limited to the permissions granted via the second grant block. I package my application into a single MyApp.jar file and generally speaking this works fine and raises an AccessControlException everytime someone tries to call java.lang.System.exit()
from my ScriptEngine, etc.
Now onto the problem - if I place my the jar file onto a network share (\\global\fs\Technology\Tools\MyApp.jar
) then my application fails to load as the "AllPermission" grant block doesn't seem to match my codebase.
Has anyone else come across this problem and knows how to resolve it - this only happens for network drives and not if I place it anywhere else.
Here is the debug output -
java -Djava.security.manager -Djava.security.policy=mypolicy -Djava.security.debug=access -jar \\global\fs\Technology\Tools\MyApp.jar
Which results in the following error messages:
access: access allowed ("java.io.FilePermission" "\\global\fs\Technology\Tools\MyApp.jar" "read")
access: access allowed ("java.util.PropertyPermission" "os.version" "read")
access: access allowed ("java.util.PropertyPermission" "swing.useSystemFontSettings" "read")
access: access allowed ("java.util.PropertyPermission" "os.name" "read")
access: access allowed ("java.util.PropertyPermission" "java.home" "read")
access: access allowed ("java.io.FilePermission" "C:\Program Files\Java\jre1.8.0_121\lib\swing.properties" "read")
access: access allowed ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
access: access allowed ("java.util.PropertyPermission" "os.version" "read")
access: access allowed ("java.util.PropertyPermission" "user.dir" "read")
access: access allowed ("java.io.FilePermission" "C:\etc\release" "read")
access: access allowed ("java.io.FilePermission" "\etc\release" "read")
access: access allowed ("java.util.PropertyPermission" "swing.showFromDoubleBuffer" "read")
access: access allowed ("java.util.PropertyPermission" "swing.nativeErase" "read")
access: access denied ("java.awt.AWTPermission" "showWindowWithoutWarningBanner")
access: access allowed ("java.util.PropertyPermission" "awt.appletWarning" "read")
access: access allowed ("java.util.PropertyPermission" "java.home" "read")
access: access allowed ("java.util.PropertyPermission" "sun.awt.nopixfmt" "read")
access: access allowed ("java.util.PropertyPermission" "swing.logDoubleBufferingDisable" "read")
access: access allowed ("java.util.PropertyPermission" "swing.ignoreDoubleBufferingDisable" "read")
access: access allowed ("java.lang.RuntimePermission" "createClassLoader")
access: access allowed ("java.lang.RuntimePermission" "createClassLoader")
access: access allowed ("java.lang.RuntimePermission" "accessClassInPackage.sun.reflect.misc")
.. (removed for brevity)
access: access allowed ("java.util.PropertyPermission" "os.name" "read")
access: access allowed ("java.util.PropertyPermission" "java.util.prefs.PreferencesFactory" "read")
access: access allowed ("java.util.PropertyPermission" "os.name" "read")
access: access allowed ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
access: access denied ("java.lang.RuntimePermission" "preferences")
Exception in thread "AWT-EventQueue-0" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "preferences")
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.util.prefs.Preferences.userRoot(Unknown Source)
at e.<init>(Unknown Source)
at e.<init>(Unknown Source)
at MyApp.<init>(Unknown Source)
at a.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
I have even tried referencing the codeBase exactly as above, but I still have the same issues:
grant codeBase "file:\\global\fs\Technology\Tools\MyApp.jar" {
permission java.security.AllPermission;
};
UPDATE Further debugging has shown what looks to be a bug in Java?? I have matched the "Active CodeSource" exactly in the policy file and it still rejects it:
grant codeBase "file:/-" {
permission java.security.AllPermission;
};
grant codeBase "file://global/fs/Technology/Tools/MyApp.jar" {
permission java.security.AllPermission;
};
grant {
permission java.net.SocketPermission "*", "accept,connect,resolve";
};
With policy
debugging, I am seeing the following (I do notice that file:/-
changes to only permit my current C: drive):
C:\Users\Default> java -Djava.security.manager -Djava.security.policy=mypolicy -Djava.security.debug=policy -jar \\global\fs\Technology\Tools\MyApp.jar
policy: evaluate codesources:
Policy CodeSource: (file:/C:/- <no signer certificates>)
Active CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
policy: evaluation (codesource) failed
policy: evaluate codesources:
Policy CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
Active CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
policy: evaluation (codesource) failed
policy: evaluate codesources:
Policy CodeSource: (null <no signer certificates>)
Active CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
policy: evaluate principals:
Policy Principals: []
Active Principals: []
policy: granting ("java.net.SocketPermission" "*" "connect,accept,resolve")
As you can see, it is comparing the "Policy CodeSource" with the "Active CodeSource" and saying they don't match even though they are identical?!? As they don't match it is falling through to my generic grant block which is only granting limited permissions.
This only appears to happen if my current working directory is on a different drive or filesystem to my JAR file.
Is it not possible to grant permissions to "MyApp.jar" regardless of path?