java.net.NetPermission "specifyStreamHandler" not allowed for custom plugin

I presume this issue is analogous to java.io.FilePermission is no longer allowed for custom plug-in. · Issue #69464 · elastic/elasticsearch · GitHub, but dealing with java.net.NetPermission "specifyStreamHandler" permission instead.

elasticsearch --version
Version: 7.17.1, Build: default/tar/e5acb99f822233d62d6444ce45a4543dc1c8059a/2022-02-23T22:20:54.153567231Z, JVM: 17.0.2

uname -a
Darwin mac.local 21.2.0 Darwin Kernel Version 21.2.0: Sun Nov 28 20:28:54 PST 2021; root:xnu-8019.61.5~1/RELEASE_X86_64 x86_64

We have developed a custom ML scoring plugin that uses Scala scripts to calculate features.
Scala scripts are evaluated at runtime with eval. It is done more or less by the following code

	import scala.reflect.runtime.currentMirror
	import scala.tools.reflect.ToolBox
	val toolbox = currentMirror.mkToolBox()
	toolbox.eval(toolbox.parse(featureScript))

wrapped in AccessController.doPrivileged.

We use the following plugin-security.policy file:

	grant {
			permission java.net.NetPermission "specifyStreamHandler";
			permission java.lang.RuntimePermission "getClassLoader";
			permission java.lang.RuntimePermission "createClassLoader";
			permission java.lang.RuntimePermission "accessDeclaredMembers";
			permission java.lang.RuntimePermission "accessClassInPackage.jdk.*";
			permission java.lang.RuntimePermission "accessClassInPackage.sun.*";
			permission java.util.PropertyPermission "*", "read,write";
	};

It works as expected in 7.9 but fails to install with 7.17

Exception in thread "main" java.lang.IllegalArgumentException: plugin policy [...] contains illegal permission ("java.net.NetPermission" "specifyStreamHandler") in global grant
        at org.elasticsearch.bootstrap.PolicyUtil.validatePolicyPermissionsForJar(PolicyUtil.java:350)
        at org.elasticsearch.bootstrap.PolicyUtil.validatePolicyPermissions(PolicyUtil.java:360)
        at org.elasticsearch.bootstrap.PolicyUtil.getPluginPolicyInfo(PolicyUtil.java:371)
        at org.elasticsearch.plugins.cli.InstallPluginAction.installPlugin(InstallPluginAction.java:889)
        at org.elasticsearch.plugins.cli.InstallPluginAction.execute(InstallPluginAction.java:245)
        at org.elasticsearch.plugins.cli.InstallPluginCommand.execute(InstallPluginCommand.java:88)
        at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:77)
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:112)
        at org.elasticsearch.cli.MultiCommand.execute(MultiCommand.java:95)
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:112)
        at org.elasticsearch.cli.Command.main(Command.java:77)
        at org.elasticsearch.plugins.cli.PluginCli.main(PluginCli.java:36)

If I remove this permission from plugin-security.policy then plugin can be installed but upon usage the following exception occurs

Caused by: java.security.AccessControlException: access denied ("java.net.NetPermission" "specifyStreamHandler")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:485) ~[?:?]
	at java.security.AccessController.checkPermission(AccessController.java:1068) ~[?:?]
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:416) ~[?:?]
	at java.net.URL.checkSpecifyHandler(URL.java:776) ~[?:?]
	at java.net.URL.<init>(URL.java:609) ~[?:?]
	at scala.reflect.internal.util.AbstractFileClassLoader.findResource(AbstractFileClassLoader.scala:81) ~[?:?]
	at java.lang.ClassLoader.getResource(ClassLoader.java:1403) ~[?:?]
	at java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:1733) ~[?:?]
	at scala.reflect.internal.util.RichClassLoader$.classAsStream$extension(ScalaClassLoader.scala:89) ~[?:?]
	at scala.reflect.internal.util.RichClassLoader$.classBytes$extension(ScalaClassLoader.scala:81) ~[?:?]
	at scala.reflect.internal.util.ScalaClassLoader.classBytes(ScalaClassLoader.scala:131) ~[?:?]
	at scala.reflect.internal.util.ScalaClassLoader.classBytes$(ScalaClassLoader.scala:131) ~[?:?]
	at scala.reflect.internal.util.AbstractFileClassLoader.classBytes(AbstractFileClassLoader.scala:43) ~[?:?]
	at scala.reflect.internal.util.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:73) ~[?:?]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:587) ~[?:?]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
	at java.lang.Class.forName0(Native Method) ~[?:?]
	at java.lang.Class.forName(Class.java:467) ~[?:?]
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.compile(ToolBoxFactory.scala:273) ~[?:?]
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.$anonfun$compile$13(ToolBoxFactory.scala:445) ~[?:?]
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory.scala:371) ~[?:?]
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:438) ~[?:?]
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:460) ~[?:?]

Allowed permission are listed in https://github.com/elastic/elasticsearch/blob/7.17/server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java.
specifyStreamHandler is not among them.

Not sure whether it is intended behaviour or a bug. Want to confirm it before opening a github issue.

Hey,

while it might make sense to open a GitHub issue about this, the main question is, if you can probably get away from trying to load a resource via Class.getResourceAsStream, if that library also allows to load that resource via a system property, or specifying a different constructor allowing you to read that data via a file - hypothesizing here only, but maybe there is another way.

--Alex

Hi,

Thank you for the quick reply and for the suggestion.

We managed to solve this issue by using a custom classloader with method Class.getResourceAsStream overridden. Though unelegant and requiring to change a part of the mentioned library, this solution works.

Have a good day!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.