This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 4_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/4_0_X by this push:
new 5bab386cef Strengthen Groovy sandbox
5bab386cef is described below
commit 5bab386cef01a0a0ee620648ce12f067ad14d1eb
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Tue Oct 20 16:39:14 2026 +0200
Strengthen Groovy sandbox
---
.../src/main/resources/META-INF/groovy.blacklist | 10 +
.../spring/implementation/GroovySandboxTest.java | 218 +++++++++++----------
...ProcessGroovyMethodsSchedTaskJobDelegate.groovy | 30 +++
.../ThreadLocalBypassSchedTaskJobDelegate.groovy | 47 +++++
pom.xml | 2 +-
5 files changed, 207 insertions(+), 100 deletions(-)
diff --git a/core/spring/src/main/resources/META-INF/groovy.blacklist
b/core/spring/src/main/resources/META-INF/groovy.blacklist
index cfe5dfeccd..4d22b3f751 100644
--- a/core/spring/src/main/resources/META-INF/groovy.blacklist
+++ b/core/spring/src/main/resources/META-INF/groovy.blacklist
@@ -250,3 +250,13 @@ staticMethod
org.codehaus.groovy.runtime.ScriptBytecodeAdapter castToType java.l
# SECURITY-1754
new org.kohsuke.groovy.sandbox.impl.Checker$SuperConstructorWrapper
java.lang.Object[]
new org.kohsuke.groovy.sandbox.impl.Checker$ThisConstructorWrapper
java.lang.Object[]
+
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.String
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.String java.lang.String[] java.io.File
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.String[]
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.String[] java.lang.String[] java.io.File
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.util.List
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.util.List java.lang.String[] java.io.File
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.Runtime java.lang.String
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.Runtime java.lang.String java.lang.String[] java.io.File
+staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods execute
java.lang.Runtime java.lang.String[]
diff --git
a/core/spring/src/test/java/org/apache/syncope/core/spring/implementation/GroovySandboxTest.java
b/core/spring/src/test/java/org/apache/syncope/core/spring/implementation/GroovySandboxTest.java
index e821ce4699..9f8b408857 100644
---
a/core/spring/src/test/java/org/apache/syncope/core/spring/implementation/GroovySandboxTest.java
+++
b/core/spring/src/test/java/org/apache/syncope/core/spring/implementation/GroovySandboxTest.java
@@ -32,7 +32,10 @@ import java.util.Objects;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.provisioning.api.job.JobExecutionException;
+import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
import org.apache.syncope.core.provisioning.api.macro.MacroActions;
import org.apache.syncope.core.spring.SpringTestConfiguration;
import org.junit.jupiter.api.Test;
@@ -45,19 +48,7 @@ import
org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = { SpringTestConfiguration.class })
class GroovySandboxTest {
- @TempDir
- private Path tempDir;
-
- @Test
- void processBuilder() throws Exception {
- final MacroActions actions = actions("processBuilder",
"/ProcessBuilderMacroActions.groovy");
-
- final SecurityException e = assertThrows(
- SecurityException.class, () -> actions.afterAll(null, new
StringBuilder()));
- assertTrue(e.getMessage().contains("Insecure call to 'new
java.lang.ProcessBuilder java.lang.String[]'"));
- }
-
- private static MacroActions actions(final String key, final String
resource) throws Exception {
+ private static <T> T build(final String key, final String resource) throws
Exception {
Implementation impl = mock(Implementation.class);
when(impl.getKey()).thenReturn(key);
when(impl.getEngine()).thenReturn(ImplementationEngine.GROOVY);
@@ -68,34 +59,45 @@ class GroovySandboxTest {
return ImplementationManager.build(SyncopeConstants.MASTER_DOMAIN,
impl);
}
+ @TempDir
+ private Path tempDir;
+
+ @Test
+ void processBuilder() throws Exception {
+ MacroActions actions = build("processBuilder",
"/ProcessBuilderMacroActions.groovy");
+
+ SecurityException e = assertThrows(
+ SecurityException.class, () -> actions.afterAll(null, new
StringBuilder()));
+ assertTrue(e.getMessage().contains("Insecure call to 'new
java.lang.ProcessBuilder java.lang.String[]'"));
+ }
+
@EnabledOnOs(OS.LINUX)
@Test
void bash() throws Exception {
- final MacroActions actions = actions("bash",
"/BashMacroActions.groovy");
+ MacroActions actions = build("bash", "/BashMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class, () -> actions.afterAll(null, new
StringBuilder()));
assertTrue(e.getMessage().contains("Insecure call to 'new java.io.File
java.lang.String'"));
}
@Test
void staticMacroActions() throws Exception {
- final BeanCreationException e =
- assertThrows(
- BeanCreationException.class,
- () -> actions("staticMacroActions",
"/StaticMacroActions.groovy"));
- final SecurityException sec = (SecurityException)
ExceptionUtils.getRootCause(e);
+ BeanCreationException e = assertThrows(
+ BeanCreationException.class,
+ () -> build("staticMacroActions",
"/StaticMacroActions.groovy"));
+ SecurityException sec = (SecurityException)
ExceptionUtils.getRootCause(e);
assertTrue(sec.getMessage().startsWith("Insecure call to 'new
java.lang.ProcessBuilder java.util.List'"));
}
@Test
void pathOfFilesReadString() throws Exception {
- final Path testFile = tempDir.resolve("sandbox-read.txt");
+ Path testFile = tempDir.resolve("sandbox-read.txt");
Files.writeString(testFile, "sandbox-read-ok");
- final MacroActions actions = actions("pathOfFilesReadString",
"/PathOfFilesReadStringMacroActions.groovy");
+ MacroActions actions = build("pathOfFilesReadString",
"/PathOfFilesReadStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toAbsolutePath().toString())));
assertTrue(e.getMessage().contains(
@@ -104,11 +106,11 @@ class GroovySandboxTest {
@Test
void pathOfFilesWriteString() throws Exception {
- final Path testFile = tempDir.resolve("sandbox-write.txt");
+ Path testFile = tempDir.resolve("sandbox-write.txt");
- final MacroActions actions = actions("pathOfFilesWriteString",
"/PathOfFilesWriteStringMacroActions.groovy");
+ MacroActions actions = build("pathOfFilesWriteString",
"/PathOfFilesWriteStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toAbsolutePath().toString())));
assertTrue(e.getMessage().contains(
@@ -117,13 +119,12 @@ class GroovySandboxTest {
@Test
void pathOfUriFilesReadString() throws Exception {
- final Path testFile = tempDir.resolve("sandbox-read-uri.txt");
+ Path testFile = tempDir.resolve("sandbox-read-uri.txt");
Files.writeString(testFile, "sandbox-read-uri-ok");
- final MacroActions actions =
- actions("pathOfUriFilesReadString",
"/PathOfUriFilesReadStringMacroActions.groovy");
+ MacroActions actions = build("pathOfUriFilesReadString",
"/PathOfUriFilesReadStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toUri().toString())));
assertTrue(e.getMessage().contains(
@@ -132,12 +133,12 @@ class GroovySandboxTest {
@Test
void pathsGetFilesReadString() throws Exception {
- final Path testFile = tempDir.resolve("sandbox-paths-get-read.txt");
+ Path testFile = tempDir.resolve("sandbox-paths-get-read.txt");
Files.writeString(testFile, "sandbox-paths-get-read-ok");
- final MacroActions actions = actions("pathsGetFilesReadString",
"/PathsGetFilesReadStringMacroActions.groovy");
+ MacroActions actions = build("pathsGetFilesReadString",
"/PathsGetFilesReadStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toAbsolutePath().toString())));
assertTrue(e.getMessage().contains(
@@ -146,13 +147,12 @@ class GroovySandboxTest {
@Test
void pathsGetUriFilesReadString() throws Exception {
- final Path testFile =
tempDir.resolve("sandbox-paths-get-uri-read.txt");
+ Path testFile = tempDir.resolve("sandbox-paths-get-uri-read.txt");
Files.writeString(testFile, "sandbox-paths-get-uri-read-ok");
- final MacroActions actions =
- actions("pathsGetUriFilesReadString",
"/PathsGetUriFilesReadStringMacroActions.groovy");
+ MacroActions actions = build("pathsGetUriFilesReadString",
"/PathsGetUriFilesReadStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toUri().toString())));
assertTrue(e.getMessage().contains(
@@ -161,12 +161,12 @@ class GroovySandboxTest {
@Test
void fileSystemsReadString() throws Exception {
- final Path testFile = tempDir.resolve("sandbox-filesystems-read.txt");
+ Path testFile = tempDir.resolve("sandbox-filesystems-read.txt");
Files.writeString(testFile, "sandbox-filesystems-read-ok");
- final MacroActions actions = actions("fileSystemsReadString",
"/FileSystemsReadStringMacroActions.groovy");
+ MacroActions actions = build("fileSystemsReadString",
"/FileSystemsReadStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toAbsolutePath().toString())));
assertTrue(e.getMessage().contains(
@@ -175,13 +175,13 @@ class GroovySandboxTest {
@Test
void fileSystemProviderReadString() throws Exception {
- final Path testFile =
tempDir.resolve("sandbox-filesystem-provider-read.txt");
+ Path testFile =
tempDir.resolve("sandbox-filesystem-provider-read.txt");
Files.writeString(testFile, "sandbox-filesystem-provider-read-ok");
- final MacroActions actions =
- actions("fileSystemProviderReadString",
"/FileSystemProviderReadStringMacroActions.groovy");
+ MacroActions actions =
+ build("fileSystemProviderReadString",
"/FileSystemProviderReadStringMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new
StringBuilder(testFile.toUri().toString())));
assertTrue(e.getMessage().contains(
@@ -190,9 +190,9 @@ class GroovySandboxTest {
@Test
void filesCreateTempFile() throws Exception {
- final MacroActions actions = actions("filesCreateTempFile",
"/FilesCreateTempFileMacroActions.groovy");
+ MacroActions actions = build("filesCreateTempFile",
"/FilesCreateTempFileMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -202,10 +202,9 @@ class GroovySandboxTest {
@Test
void filesCreateTempDirectory() throws Exception {
- final MacroActions actions =
- actions("filesCreateTempDirectory",
"/FilesCreateTempDirectoryMacroActions.groovy");
+ MacroActions actions = build("filesCreateTempDirectory",
"/FilesCreateTempDirectoryMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -216,16 +215,14 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void processBuilderStartPipeline() throws Exception {
- final MacroActions actions =
- actions("processBuilderStartPipeline",
"/ProcessBuilderStartPipelineMacroActions.groovy");
+ MacroActions actions = build("processBuilderStartPipeline",
"/ProcessBuilderStartPipelineMacroActions.groovy");
@SuppressWarnings("unchecked")
- final Map<String, java.io.Serializable> ctx =
- (Map<String, java.io.Serializable>) (Map<?, ?>) Map.of(
- "builders",
- List.of(new ProcessBuilder("/bin/sh", "-c", "printf
sandbox-start-pipeline-ok")));
+ Map<String, java.io.Serializable> ctx = (Map<String,
java.io.Serializable>) (Map<?, ?>) Map.of(
+ "builders",
+ List.of(new ProcessBuilder("/bin/sh", "-c", "printf
sandbox-start-pipeline-ok")));
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(ctx, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -235,13 +232,13 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void runtimeExec() throws Exception {
- final MacroActions actions = actions("runtimeExec",
"/RuntimeExecMacroActions.groovy");
+ MacroActions actions = build("runtimeExec",
"/RuntimeExecMacroActions.groovy");
@SuppressWarnings("unchecked")
- final Map<String, java.io.Serializable> ctx =
+ Map<String, java.io.Serializable> ctx =
(Map<String, java.io.Serializable>) (Map<?, ?>)
Map.of("runtime", Runtime.getRuntime());
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(ctx, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -251,10 +248,9 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void beansExpressionRuntimeExec() throws Exception {
- final MacroActions actions =
- actions("beansExpressionRuntimeExec",
"/BeansExpressionRuntimeExecMacroActions.groovy");
+ MacroActions actions = build("beansExpressionRuntimeExec",
"/BeansExpressionRuntimeExecMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -263,10 +259,9 @@ class GroovySandboxTest {
@Test
void beansStatementSystemExit() throws Exception {
- final MacroActions actions =
- actions("beansStatementSystemExit",
"/BeansStatementSystemExitMacroActions.groovy");
+ MacroActions actions = build("beansStatementSystemExit",
"/BeansStatementSystemExitMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -276,9 +271,9 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void groovyShellRuntimeExec() throws Exception {
- final MacroActions actions = actions("groovyShellRuntimeExec",
"/GroovyShellRuntimeExecMacroActions.groovy");
+ MacroActions actions = build("groovyShellRuntimeExec",
"/GroovyShellRuntimeExecMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains("Insecure call to 'new
groovy.lang.GroovyShell'"));
@@ -287,9 +282,9 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void evalRuntimeExec() throws Exception {
- final MacroActions actions = actions("evalRuntimeExec",
"/EvalRuntimeExecMacroActions.groovy");
+ MacroActions actions = build("evalRuntimeExec",
"/EvalRuntimeExecMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -299,10 +294,9 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void methodHandlesRuntimeExec() throws Exception {
- final MacroActions actions =
- actions("methodHandlesRuntimeExec",
"/MethodHandlesRuntimeExecMacroActions.groovy");
+ MacroActions actions = build("methodHandlesRuntimeExec",
"/MethodHandlesRuntimeExecMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -312,13 +306,13 @@ class GroovySandboxTest {
@EnabledOnOs(OS.LINUX)
@Test
void runtimeExecOverloads() throws Exception {
- final MacroActions actions = actions("runtimeExecOverloads",
"/RuntimeExecOverloadsMacroActions.groovy");
+ MacroActions actions = build("runtimeExecOverloads",
"/RuntimeExecOverloadsMacroActions.groovy");
@SuppressWarnings("unchecked")
- final Map<String, java.io.Serializable> ctx =
+ Map<String, java.io.Serializable> ctx =
(Map<String, java.io.Serializable>) (Map<?, ?>)
Map.of("runtime", Runtime.getRuntime());
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(ctx, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -327,9 +321,9 @@ class GroovySandboxTest {
@Test
void evalOverloads() throws Exception {
- final MacroActions actions = actions("evalOverloads",
"/EvalOverloadsMacroActions.groovy");
+ MacroActions actions = build("evalOverloads",
"/EvalOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -338,15 +332,15 @@ class GroovySandboxTest {
@Test
void groovyShellOverloads() throws Exception {
- final Path script =
tempDir.resolve("sandbox-groovy-shell-overload.groovy");
+ Path script = tempDir.resolve("sandbox-groovy-shell-overload.groovy");
Files.writeString(script, "return 'shell-evaluate-file|'");
@SuppressWarnings("unchecked")
- final Map<String, java.io.Serializable> ctx =
+ Map<String, java.io.Serializable> ctx =
(Map<String, java.io.Serializable>) (Map<?, ?>)
Map.of("scriptFile", script.toFile());
- final MacroActions actions = actions("groovyShellOverloads",
"/GroovyShellOverloadsMacroActions.groovy");
+ MacroActions actions = build("groovyShellOverloads",
"/GroovyShellOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(ctx, new StringBuilder()));
assertTrue(e.getMessage().contains("Insecure call to 'new
groovy.lang.GroovyShell'"));
@@ -354,10 +348,10 @@ class GroovySandboxTest {
@Test
void groovyClassLoaderOverloads() throws Exception {
- final MacroActions actions =
- actions("groovyClassLoaderOverloads",
"/GroovyClassLoaderOverloadsMacroActions.groovy");
+ MacroActions actions = build(
+ "groovyClassLoaderOverloads",
"/GroovyClassLoaderOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains("Insecure call to 'new
groovy.lang.GroovyClassLoader'"));
@@ -365,9 +359,9 @@ class GroovySandboxTest {
@Test
void scriptEngineOverloads() throws Exception {
- final MacroActions actions = actions("scriptEngineOverloads",
"/ScriptEngineOverloadsMacroActions.groovy");
+ MacroActions actions = build("scriptEngineOverloads",
"/ScriptEngineOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains("Insecure call to 'new
javax.script.ScriptEngineManager'"));
@@ -375,15 +369,15 @@ class GroovySandboxTest {
@Test
void fileSystemsOverloads() throws Exception {
- final Path file = tempDir.resolve("sandbox-filesystems-overloads.txt");
+ Path file = tempDir.resolve("sandbox-filesystems-overloads.txt");
Files.writeString(file, "sandbox-filesystems-overloads-ok");
@SuppressWarnings("unchecked")
- final Map<String, java.io.Serializable> ctx =
+ Map<String, java.io.Serializable> ctx =
(Map<String, java.io.Serializable>) (Map<?, ?>) Map.of("path",
file);
- final MacroActions actions = actions("fileSystemsOverloads",
"/FileSystemsOverloadsMacroActions.groovy");
+ MacroActions actions = build("fileSystemsOverloads",
"/FileSystemsOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(ctx, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -392,18 +386,17 @@ class GroovySandboxTest {
@Test
void fileSystemProviderOverloads() throws Exception {
- final Path file =
tempDir.resolve("sandbox-filesystem-provider-overloads.txt");
+ Path file =
tempDir.resolve("sandbox-filesystem-provider-overloads.txt");
Files.writeString(file, "sandbox-filesystem-provider-overloads-ok");
@SuppressWarnings("unchecked")
- final Map<String, java.io.Serializable> ctx =
+ Map<String, java.io.Serializable> ctx =
(Map<String, java.io.Serializable>) (Map<?, ?>) Map.of(
"path", file,
"provider", file.getFileSystem().provider());
- final MacroActions actions =
- actions("fileSystemProviderOverloads",
"/FileSystemProviderOverloadsMacroActions.groovy");
+ MacroActions actions = build("fileSystemProviderOverloads",
"/FileSystemProviderOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(ctx, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -412,9 +405,9 @@ class GroovySandboxTest {
@Test
void methodHandlesOverloads() throws Exception {
- final MacroActions actions = actions("methodHandlesOverloads",
"/MethodHandlesOverloadsMacroActions.groovy");
+ MacroActions actions = build("methodHandlesOverloads",
"/MethodHandlesOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
@@ -423,12 +416,39 @@ class GroovySandboxTest {
@Test
void beansOverloads() throws Exception {
- final MacroActions actions = actions("beansOverloads",
"/BeansOverloadsMacroActions.groovy");
+ MacroActions actions = build("beansOverloads",
"/BeansOverloadsMacroActions.groovy");
- final SecurityException e = assertThrows(
+ SecurityException e = assertThrows(
SecurityException.class,
() -> actions.afterAll(null, new StringBuilder()));
assertTrue(e.getMessage().contains(
"Insecure call to 'new java.beans.Expression java.lang.Object
java.lang.String java.lang.Object[]'"));
}
+
+ @EnabledOnOs(OS.LINUX)
+ @Test
+ void processGroovyMethodsSchedTaskJobDelegate() throws Exception {
+ SchedTaskJobDelegate delegate = build(
+ "processGroovyMethodsSchedTaskJobDelegate",
"/ProcessGroovyMethodsSchedTaskJobDelegate.groovy");
+
+ SecurityException e = assertThrows(
+ SecurityException.class,
+ () -> delegate.execute(TaskType.SCHEDULED, null, null));
+ assertTrue(e.getMessage().contains(
+ "Insecure call to 'staticMethod
org.codehaus.groovy.runtime.ProcessGroovyMethods "
+ + "execute java.lang.String'"));
+ }
+
+ @EnabledOnOs(OS.LINUX)
+ @Test
+ void threadLocalBypassSchedTaskJobDelegate() throws Exception {
+ SchedTaskJobDelegate delegate = build("threadLocalBypass",
"/ThreadLocalBypassSchedTaskJobDelegate.groovy");
+
+ JobExecutionException e = assertThrows(
+ JobExecutionException.class,
+ () -> delegate.execute(TaskType.SCHEDULED, null, null));
+ assertTrue(e.getMessage().contains(
+ "Insecure call to 'staticMethod
org.codehaus.groovy.runtime.ProcessGroovyMethods "
+ + "execute java.lang.String'"));
+ }
}
diff --git
a/core/spring/src/test/resources/ProcessGroovyMethodsSchedTaskJobDelegate.groovy
b/core/spring/src/test/resources/ProcessGroovyMethodsSchedTaskJobDelegate.groovy
new file mode 100644
index 0000000000..bd9021b1ae
--- /dev/null
+++
b/core/spring/src/test/resources/ProcessGroovyMethodsSchedTaskJobDelegate.groovy
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate
+import org.apache.syncope.core.provisioning.api.job.JobExecutionContext
+import org.apache.syncope.core.provisioning.api.job.JobExecutionException
+import org.apache.syncope.common.lib.types.TaskType
+
+class ProcessGroovyMethodsSchedTaskJobDelegate implements SchedTaskJobDelegate
{
+
+ void execute(TaskType taskType, String taskKey, JobExecutionContext context)
throws JobExecutionException {
+ def output = "id".execute().text
+ throw new JobExecutionException("RCE_OUTPUT: " + output)
+ }
+}
diff --git
a/core/spring/src/test/resources/ThreadLocalBypassSchedTaskJobDelegate.groovy
b/core/spring/src/test/resources/ThreadLocalBypassSchedTaskJobDelegate.groovy
new file mode 100644
index 0000000000..188bd4bf53
--- /dev/null
+++
b/core/spring/src/test/resources/ThreadLocalBypassSchedTaskJobDelegate.groovy
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate
+import org.apache.syncope.core.provisioning.api.job.JobExecutionContext
+import org.apache.syncope.core.provisioning.api.job.JobExecutionException
+import org.apache.syncope.common.lib.types.TaskType
+import java.util.concurrent.atomic.AtomicReference
+
+class ThreadLocalBypassSchedTaskJobDelegate implements SchedTaskJobDelegate {
+
+ void execute(TaskType taskType, String taskKey, JobExecutionContext context)
throws JobExecutionException {
+ def result = new AtomicReference("NOT_SET")
+ def runnable = new RceRunner(result)
+ def t = new Thread((Runnable) runnable)
+ t.start()
+ t.join(5000)
+ throw new JobExecutionException("THREAD_RCE: " + result.get())
+ }
+}
+
+class RceRunner implements Runnable {
+ AtomicReference result
+ RceRunner(AtomicReference r) { this.result = r }
+ void run() {
+ try {
+ result.set("whoami".execute().text)
+ } catch (Exception e) {
+ result.set("ERROR: " + e.getMessage())
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index 52284a8d7c..a24a42e8a4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1027,7 +1027,7 @@ under the License.
<dependency>
<groupId>net.tirasa</groupId>
<artifactId>groovy-security-sandbox</artifactId>
- <version>1.0.0</version>
+ <version>1.1.0-SNAPSHOT</version>
</dependency>
<!-- Flowable -->