From f3c4a246cc39b1a4cd346046cbcdad82ce4c2e7d Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 13 Feb 2025 15:02:57 +0100 Subject: [PATCH 1/9] [Entitlements] Instrument nio path --- .../bridge/EntitlementChecker.java | 15 +++++++ .../qa/test/RestEntitlementsCheckAction.java | 2 +- .../EntitlementInitialization.java | 44 ++++++++++++++++++- .../api/ElasticsearchEntitlementChecker.java | 39 ++++++++++++++++ 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java index 39671e298cb97..216965bb912d2 100644 --- a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java +++ b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java @@ -58,6 +58,8 @@ import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; +import java.nio.file.WatchEvent; +import java.nio.file.WatchService; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.UserPrincipal; import java.nio.file.spi.FileSystemProvider; @@ -652,4 +654,17 @@ void checkNewByteChannel( void checkName(Class callerClass, FileStore that); void checkType(Class callerClass, FileStore that); + + // path + void checkPathToRealPath(Class callerClass, Path that, LinkOption... options); + + void checkPathRegister(Class callerClass, Path that, WatchService watcher, WatchEvent.Kind... events); + + void checkPathRegister( + Class callerClass, + Path that, + WatchService watcher, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers + ); } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java index 18709465fe1a8..cad8c37ec8390 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java @@ -187,7 +187,7 @@ static CheckAction alwaysDenied(CheckedRunnable action) { getTestEntries(SystemActions.class), getTestEntries(NativeActions.class), getTestEntries(NioFileSystemActions.class), - getTestEntries(FileStoreActions.class) + getTestEntries(PathActions.class) ) .flatMap(Function.identity()) .filter(entry -> entry.getValue().fromJavaVersion() == null || Runtime.version().feature() >= entry.getValue().fromJavaVersion()) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java index 331d47e561f19..1bff3480d9d98 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java @@ -44,6 +44,8 @@ import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; +import java.nio.file.WatchEvent; +import java.nio.file.WatchService; import java.nio.file.attribute.FileAttribute; import java.nio.file.spi.FileSystemProvider; import java.util.ArrayList; @@ -58,6 +60,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ; import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ_WRITE; /** @@ -94,6 +97,7 @@ public static void initialize(Instrumentation inst) throws Exception { Stream.of( fileSystemProviderChecks(), fileStoreChecks(), + pathChecks(), Stream.of( INSTRUMENTATION_SERVICE.lookupImplementationMethod( SelectorProvider.class, @@ -144,13 +148,22 @@ private static PolicyManager createPolicyManager() { new OutboundNetworkEntitlement(), new LoadNativeLibrariesEntitlement(), new FilesEntitlement( - List.of(new FilesEntitlement.FileData(EntitlementBootstrap.bootstrapArgs().tempDir().toString(), READ_WRITE)) + Stream.concat( + Stream.of(new FileData(EntitlementBootstrap.bootstrapArgs().tempDir().toString(), READ_WRITE)), + Arrays.stream(dataDirs).map(d -> new FileData(d.toString(), READ)) + ).toList() ) ) ), new Scope("org.apache.httpcomponents.httpclient", List.of(new OutboundNetworkEntitlement())), new Scope("io.netty.transport", List.of(new InboundNetworkEntitlement(), new OutboundNetworkEntitlement())), - new Scope("org.apache.lucene.core", List.of(new LoadNativeLibrariesEntitlement())), + new Scope( + "org.apache.lucene.core", + List.of( + new LoadNativeLibrariesEntitlement(), + new FilesEntitlement(Arrays.stream(dataDirs).map(d -> new FileData(d.toString(), READ_WRITE)).toList()) + ) + ), new Scope( "org.elasticsearch.nativeaccess", List.of( @@ -255,6 +268,33 @@ public InstrumentationService.InstrumentationInfo of(String methodName, Class }); } + private static Stream pathChecks() { + var pathClasses = StreamSupport.stream(FileSystems.getDefault().getRootDirectories().spliterator(), false) + .map(Path::getClass) + .distinct(); + return pathClasses.flatMap(pathClass -> { + InstrumentationInfoFactory instrumentation = (String methodName, Class... parameterTypes) -> INSTRUMENTATION_SERVICE + .lookupImplementationMethod( + Path.class, + methodName, + pathClass, + EntitlementChecker.class, + "checkPath" + Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1), + parameterTypes + ); + + try { + return Stream.of( + instrumentation.of("toRealPath", LinkOption[].class), + instrumentation.of("register", WatchService.class, WatchEvent.Kind[].class), + instrumentation.of("register", WatchService.class, WatchEvent.Kind[].class, WatchEvent.Modifier[].class) + ); + } catch (NoSuchMethodException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }); + } + /** * Returns the "most recent" checker class compatible with the current runtime Java version. * For checkers, we have (optionally) version specific classes, each with a prefix (e.g. Java23). diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index 1ca03fa876b18..59de318f88b86 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -14,6 +14,7 @@ import org.elasticsearch.entitlement.runtime.policy.PolicyManager; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.PrintWriter; @@ -64,6 +65,8 @@ import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.nio.file.WatchEvent; +import java.nio.file.WatchService; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.UserPrincipal; import java.nio.file.spi.FileSystemProvider; @@ -1322,4 +1325,40 @@ public void checkName(Class callerClass, FileStore that) { public void checkType(Class callerClass, FileStore that) { policyManager.checkReadStoreAttributes(callerClass); } + + @Override + public void checkPathToRealPath(Class callerClass, Path that, LinkOption... options) { + if (EntitlementChecker.class.isAssignableFrom(callerClass)) { + return; + } + + boolean followLinks = true; + for (LinkOption option : options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + } + } + if (followLinks) { + try { + policyManager.checkFileRead(callerClass, that.toRealPath()); + } catch (IOException e) {} + } + policyManager.checkFileRead(callerClass, that); + } + + @Override + public void checkPathRegister(Class callerClass, Path that, WatchService watcher, WatchEvent.Kind... events) { + policyManager.checkFileRead(callerClass, that); + } + + @Override + public void checkPathRegister( + Class callerClass, + Path that, + WatchService watcher, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers + ) { + policyManager.checkFileRead(callerClass, that); + } } From 052bcfd254e3a4a51f538b2a5be307afe9c82f6a Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 13 Feb 2025 15:20:41 +0100 Subject: [PATCH 2/9] [Entitlements] Instrument nio path --- .../entitlement/qa/test/PathActions.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java new file mode 100644 index 0000000000000..5ccb0fa87ebda --- /dev/null +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.entitlement.qa.test; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.LinkOption; +import java.nio.file.WatchEvent; + +import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; + +class PathActions { + + @EntitlementTest(expectedAccess = PLUGINS) + static void checkToRealPath() throws IOException { + FileCheckActions.readFile().toRealPath(); + } + + @EntitlementTest(expectedAccess = PLUGINS) + static void checkToRealPathNoFollow() throws IOException { + FileCheckActions.readFile().toRealPath(LinkOption.NOFOLLOW_LINKS); + } + + @SuppressWarnings("rawtypes") + @EntitlementTest(expectedAccess = PLUGINS) + static void checkRegister() throws IOException { + try (var watchService = FileSystems.getDefault().newWatchService()) { + FileCheckActions.readFile().register(watchService, new WatchEvent.Kind[0]); + } catch (IllegalArgumentException e) { + // intentionally no events registered + } + } + + @SuppressWarnings("rawtypes") + @EntitlementTest(expectedAccess = PLUGINS) + static void checkRegisterWithModifiers() throws IOException { + try (var watchService = FileSystems.getDefault().newWatchService()) { + FileCheckActions.readFile().register(watchService, new WatchEvent.Kind[0], new WatchEvent.Modifier[0]); + } catch (IllegalArgumentException e) { + // intentionally no events registered + } + } +} From 5ed03a13a63f133668902131bbe7cb57439a7063 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 13 Feb 2025 16:18:16 +0100 Subject: [PATCH 3/9] server --- .../initialization/EntitlementInitialization.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java index 1bff3480d9d98..8b39ea9a57480 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java @@ -149,7 +149,10 @@ private static PolicyManager createPolicyManager() { new LoadNativeLibrariesEntitlement(), new FilesEntitlement( Stream.concat( - Stream.of(new FileData(EntitlementBootstrap.bootstrapArgs().tempDir().toString(), READ_WRITE)), + Stream.of( + new FileData(EntitlementBootstrap.bootstrapArgs().tempDir().toString(), READ_WRITE), + new FileData(EntitlementBootstrap.bootstrapArgs().configDir().toString(), READ) + ), Arrays.stream(dataDirs).map(d -> new FileData(d.toString(), READ)) ).toList() ) From ea05a442d1a254e4f0b757bec95f8d476d359fbe Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 13 Feb 2025 17:01:53 +0100 Subject: [PATCH 4/9] server --- .../initialization/EntitlementInitialization.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java index 8b39ea9a57480..9d62f3defa179 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java @@ -164,7 +164,12 @@ private static PolicyManager createPolicyManager() { "org.apache.lucene.core", List.of( new LoadNativeLibrariesEntitlement(), - new FilesEntitlement(Arrays.stream(dataDirs).map(d -> new FileData(d.toString(), READ_WRITE)).toList()) + new FilesEntitlement( + Stream.concat( + Stream.of(new FileData(EntitlementBootstrap.bootstrapArgs().configDir().toString(), READ)), + Arrays.stream(dataDirs).map(d -> new FileData(d.toString(), READ_WRITE)) + ).toList() + ) ) ), new Scope( From 8cc0a71fe161d6f4b28977ba12e75439dfca150d Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 14 Feb 2025 14:06:08 +0100 Subject: [PATCH 5/9] simplify toRealPath --- .../api/ElasticsearchEntitlementChecker.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index 134bbc5e37096..bd0463560e287 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -14,7 +14,6 @@ import org.elasticsearch.entitlement.runtime.policy.PolicyManager; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.PrintWriter; @@ -1375,21 +1374,8 @@ public void checkType(Class callerClass, FileStore that) { @Override public void checkPathToRealPath(Class callerClass, Path that, LinkOption... options) { - if (EntitlementChecker.class.isAssignableFrom(callerClass)) { - return; - } - - boolean followLinks = true; - for (LinkOption option : options) { - if (option == LinkOption.NOFOLLOW_LINKS) { - followLinks = false; - } - } - if (followLinks) { - try { - policyManager.checkFileRead(callerClass, that.toRealPath()); - } catch (IOException e) {} - } + // We deliberately don't check read permissions on the returned read path if following links. + // While this allows for an "exists" check on the real target, any file operation still require adequate read permissions. policyManager.checkFileRead(callerClass, that); } From 0df07763c4200c20428a1386ae928d714ae91312 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 14 Feb 2025 16:22:31 +0100 Subject: [PATCH 6/9] Revert "simplify toRealPath" This reverts commit 8cc0a71fe161d6f4b28977ba12e75439dfca150d. --- .../api/ElasticsearchEntitlementChecker.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index bd0463560e287..134bbc5e37096 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -14,6 +14,7 @@ import org.elasticsearch.entitlement.runtime.policy.PolicyManager; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.PrintWriter; @@ -1374,8 +1375,21 @@ public void checkType(Class callerClass, FileStore that) { @Override public void checkPathToRealPath(Class callerClass, Path that, LinkOption... options) { - // We deliberately don't check read permissions on the returned read path if following links. - // While this allows for an "exists" check on the real target, any file operation still require adequate read permissions. + if (EntitlementChecker.class.isAssignableFrom(callerClass)) { + return; + } + + boolean followLinks = true; + for (LinkOption option : options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + } + } + if (followLinks) { + try { + policyManager.checkFileRead(callerClass, that.toRealPath()); + } catch (IOException e) {} + } policyManager.checkFileRead(callerClass, that); } From 1f385ab74b04f946393210bafe3aa2da9eb8a406 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 14 Feb 2025 16:27:49 +0100 Subject: [PATCH 7/9] check link for toRealPath using readSymbolicLink --- .../runtime/api/ElasticsearchEntitlementChecker.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index 134bbc5e37096..43b172db80800 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -1375,10 +1375,6 @@ public void checkType(Class callerClass, FileStore that) { @Override public void checkPathToRealPath(Class callerClass, Path that, LinkOption... options) { - if (EntitlementChecker.class.isAssignableFrom(callerClass)) { - return; - } - boolean followLinks = true; for (LinkOption option : options) { if (option == LinkOption.NOFOLLOW_LINKS) { @@ -1387,8 +1383,11 @@ public void checkPathToRealPath(Class callerClass, Path that, LinkOption... o } if (followLinks) { try { - policyManager.checkFileRead(callerClass, that.toRealPath()); - } catch (IOException e) {} + FileSystemProvider provider = that.getFileSystem().provider(); + policyManager.checkFileRead(callerClass, provider.readSymbolicLink(that)); + } catch (IOException | UnsupportedOperationException e) { + // that is not a link, or unrelated IOException or unsupported + } } policyManager.checkFileRead(callerClass, that); } From ce7ac5b8ad0249d9e9cf628265b9d6145c1eeba9 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 14 Feb 2025 16:51:55 +0100 Subject: [PATCH 8/9] pr comment --- .../runtime/api/ElasticsearchEntitlementChecker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index 43b172db80800..8cb6ac7a1392a 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -61,6 +61,7 @@ import java.nio.file.CopyOption; import java.nio.file.DirectoryStream; import java.nio.file.FileStore; +import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; @@ -1383,8 +1384,7 @@ public void checkPathToRealPath(Class callerClass, Path that, LinkOption... o } if (followLinks) { try { - FileSystemProvider provider = that.getFileSystem().provider(); - policyManager.checkFileRead(callerClass, provider.readSymbolicLink(that)); + policyManager.checkFileRead(callerClass, Files.readSymbolicLink(that)); } catch (IOException | UnsupportedOperationException e) { // that is not a link, or unrelated IOException or unsupported } From 010071527baea9a2bbb41e8833fc97aefb95c51c Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Mon, 17 Feb 2025 11:30:51 +0100 Subject: [PATCH 9/9] fix ingest-attachment with entitlements --- .../elasticsearch/ingest/attachment/TikaImpl.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/modules/ingest-attachment/src/main/java/org/elasticsearch/ingest/attachment/TikaImpl.java b/modules/ingest-attachment/src/main/java/org/elasticsearch/ingest/attachment/TikaImpl.java index 02d85ef0ecfbf..1b8bf67ff6fec 100644 --- a/modules/ingest-attachment/src/main/java/org/elasticsearch/ingest/attachment/TikaImpl.java +++ b/modules/ingest-attachment/src/main/java/org/elasticsearch/ingest/attachment/TikaImpl.java @@ -18,9 +18,11 @@ import org.apache.tika.parser.ParserDecorator; import org.elasticsearch.SpecialPermission; import org.elasticsearch.bootstrap.FilePermissionUtils; +import org.elasticsearch.core.Booleans; import org.elasticsearch.core.PathUtils; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.jdk.JarHell; +import org.elasticsearch.jdk.RuntimeVersionFeature; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -122,15 +124,22 @@ static String parse(final byte content[], final Metadata metadata, final int lim // apply additional containment for parsers, this is intersected with the current permissions // its hairy, but worth it so we don't have some XML flaw reading random crap from the FS - private static final AccessControlContext RESTRICTED_CONTEXT = new AccessControlContext( - new ProtectionDomain[] { new ProtectionDomain(null, getRestrictedPermissions()) } - ); + private static final AccessControlContext RESTRICTED_CONTEXT = isUsingSecurityManager() + ? new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, getRestrictedPermissions()) }) + : null; + + private static boolean isUsingSecurityManager() { + boolean entitlementsEnabled = Booleans.parseBoolean(System.getProperty("es.entitlements.enabled"), false) + || RuntimeVersionFeature.isSecurityManagerAvailable() == false; + return entitlementsEnabled == false; + } // compute some minimal permissions for parsers. they only get r/w access to the java temp directory, // the ability to load some resources from JARs, and read sysprops @SuppressForbidden(reason = "adds access to tmp directory") static PermissionCollection getRestrictedPermissions() { Permissions perms = new Permissions(); + // property/env access needed for parsing perms.add(new PropertyPermission("*", "read")); perms.add(new RuntimePermission("getenv.TIKA_CONFIG"));