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 2c787c64c2 Hardening on Groovy sandbox against filesystem and 
execution bypasses (#1399)
2c787c64c2 is described below

commit 2c787c64c2d1fa06fd47b9acf614eb2e8da4da84
Author: Massimiliano Perrone <[email protected]>
AuthorDate: Fri May 29 09:49:36 2026 +0200

    Hardening on Groovy sandbox against filesystem and execution bypasses 
(#1399)
---
 .../src/main/resources/META-INF/groovy.blacklist   | 140 ++++++++
 .../spring/implementation/GroovySandboxTest.java   | 396 +++++++++++++++++++--
 .../BeansExpressionRuntimeExecMacroActions.groovy  |  35 ++
 .../resources/BeansOverloadsMacroActions.groovy    |  43 +++
 .../BeansStatementSystemExitMacroActions.groovy    |  31 ++
 .../resources/EvalOverloadsMacroActions.groovy     |  34 ++
 .../resources/EvalRuntimeExecMacroActions.groovy   |  31 ++
 .../FileSystemProviderOverloadsMacroActions.groovy |  47 +++
 ...FileSystemProviderReadStringMacroActions.groovy |  32 ++
 .../FileSystemsOverloadsMacroActions.groovy        |  72 ++++
 .../FileSystemsReadStringMacroActions.groovy       |  31 ++
 .../FilesCreateTempDirectoryMacroActions.groovy    |  31 ++
 .../FilesCreateTempFileMacroActions.groovy         |  32 ++
 .../GroovyClassLoaderOverloadsMacroActions.groovy  |  40 +++
 .../GroovyShellOverloadsMacroActions.groovy        |  43 +++
 .../GroovyShellRuntimeExecMacroActions.groovy      |  31 ++
 .../MethodHandlesOverloadsMacroActions.groovy      |  59 +++
 .../MethodHandlesRuntimeExecMacroActions.groovy    |  43 +++
 .../PathOfFilesReadStringMacroActions.groovy       |  31 ++
 .../PathOfFilesWriteStringMacroActions.groovy      |  30 ++
 .../PathOfUriFilesReadStringMacroActions.groovy    |  31 ++
 .../PathsGetFilesReadStringMacroActions.groovy     |  31 ++
 .../PathsGetUriFilesReadStringMacroActions.groovy  |  31 ++
 .../ProcessBuilderStartPipelineMacroActions.groovy |  31 ++
 .../test/resources/RuntimeExecMacroActions.groovy  |  31 ++
 .../RuntimeExecOverloadsMacroActions.groovy        |  42 +++
 .../ScriptEngineOverloadsMacroActions.groovy       |  36 ++
 27 files changed, 1441 insertions(+), 24 deletions(-)

diff --git a/core/spring/src/main/resources/META-INF/groovy.blacklist 
b/core/spring/src/main/resources/META-INF/groovy.blacklist
index 85292bc608..cfe5dfeccd 100644
--- a/core/spring/src/main/resources/META-INF/groovy.blacklist
+++ b/core/spring/src/main/resources/META-INF/groovy.blacklist
@@ -16,17 +16,90 @@
 # under the License.
 
 # Reflective access to Groovy
+new groovy.lang.GroovyClassLoader
+new groovy.lang.GroovyClassLoader java.lang.ClassLoader
+new groovy.lang.GroovyClassLoader groovy.lang.GroovyClassLoader
+new groovy.lang.GroovyClassLoader java.lang.ClassLoader 
org.codehaus.groovy.control.CompilerConfiguration
+new groovy.lang.GroovyClassLoader java.lang.ClassLoader 
org.codehaus.groovy.control.CompilerConfiguration boolean
+new groovy.lang.GroovyShell
+new groovy.lang.GroovyShell groovy.lang.Binding
+new groovy.lang.GroovyShell groovy.lang.Binding 
org.codehaus.groovy.control.CompilerConfiguration
+new groovy.lang.GroovyShell groovy.lang.GroovyShell
+new groovy.lang.GroovyShell java.lang.ClassLoader
+new groovy.lang.GroovyShell java.lang.ClassLoader groovy.lang.Binding
+new groovy.lang.GroovyShell java.lang.ClassLoader groovy.lang.Binding 
org.codehaus.groovy.control.CompilerConfiguration
+new groovy.lang.GroovyShell java.lang.ClassLoader 
org.codehaus.groovy.control.CompilerConfiguration
+new groovy.lang.GroovyShell org.codehaus.groovy.control.CompilerConfiguration
+method groovy.lang.GroovyClassLoader addClasspath java.lang.String
+method groovy.lang.GroovyClassLoader addURL java.net.URL
+method groovy.lang.GroovyClassLoader defineClass java.lang.String byte[]
+method groovy.lang.GroovyClassLoader parseClass groovy.lang.GroovyCodeSource
+method groovy.lang.GroovyClassLoader parseClass groovy.lang.GroovyCodeSource 
boolean
+method groovy.lang.GroovyClassLoader parseClass java.io.File
+method groovy.lang.GroovyClassLoader parseClass java.io.Reader java.lang.String
+method groovy.lang.GroovyClassLoader parseClass java.lang.String
+method groovy.lang.GroovyClassLoader parseClass java.lang.String 
java.lang.String
+method groovy.lang.GroovyShell evaluate groovy.lang.GroovyCodeSource
+method groovy.lang.GroovyShell evaluate java.io.File
+method groovy.lang.GroovyShell evaluate java.io.Reader
+method groovy.lang.GroovyShell evaluate java.io.Reader java.lang.String
+method groovy.lang.GroovyShell evaluate java.lang.String
+method groovy.lang.GroovyShell evaluate java.lang.String java.lang.String
+method groovy.lang.GroovyShell evaluate java.lang.String java.lang.String 
java.lang.String
+method groovy.lang.GroovyShell evaluate java.net.URI
+method groovy.lang.GroovyShell parse groovy.lang.GroovyCodeSource
+method groovy.lang.GroovyShell parse groovy.lang.GroovyCodeSource 
groovy.lang.Binding
+method groovy.lang.GroovyShell parse java.io.File
+method groovy.lang.GroovyShell parse java.io.Reader
+method groovy.lang.GroovyShell parse java.io.Reader groovy.lang.Binding
+method groovy.lang.GroovyShell parse java.io.Reader java.lang.String
+method groovy.lang.GroovyShell parse java.io.Reader java.lang.String 
groovy.lang.Binding
+method groovy.lang.GroovyShell parse java.lang.String
+method groovy.lang.GroovyShell parse java.lang.String groovy.lang.Binding
+method groovy.lang.GroovyShell parse java.lang.String java.lang.String
+method groovy.lang.GroovyShell parse java.lang.String java.lang.String 
groovy.lang.Binding
+method groovy.lang.GroovyShell parse java.net.URI
+method groovy.lang.GroovyShell run groovy.lang.GroovyCodeSource 
java.lang.String[]
+method groovy.lang.GroovyShell run groovy.lang.GroovyCodeSource java.util.List
+method groovy.lang.GroovyShell run java.io.File java.lang.String[]
+method groovy.lang.GroovyShell run java.io.File java.util.List
+method groovy.lang.GroovyShell run java.io.Reader java.lang.String 
java.lang.String[]
+method groovy.lang.GroovyShell run java.io.Reader java.lang.String 
java.util.List
+method groovy.lang.GroovyShell run java.lang.String java.lang.String 
java.lang.String[]
+method groovy.lang.GroovyShell run java.lang.String java.lang.String 
java.util.List
+method groovy.lang.GroovyShell run java.net.URI java.lang.String[]
+method groovy.lang.GroovyShell run java.net.URI java.util.List
+staticMethod groovy.lang.GroovyShell withConfig groovy.lang.Closure
+staticMethod groovy.util.Eval me java.lang.String
+staticMethod groovy.util.Eval me java.lang.String java.lang.Object 
java.lang.String
+staticMethod groovy.util.Eval x java.lang.Object java.lang.String
+staticMethod groovy.util.Eval xy java.lang.Object java.lang.Object 
java.lang.String
+staticMethod groovy.util.Eval xyz java.lang.Object java.lang.Object 
java.lang.Object java.lang.String
 method groovy.lang.GroovyObject getMetaClass
 method groovy.lang.GroovyObject getProperty java.lang.String
 method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object
 method groovy.lang.GroovyObject setMetaClass groovy.lang.MetaClass
 method groovy.lang.GroovyObject setProperty java.lang.String java.lang.Object
 
+# Runtime script engines could evaluate code outside the Groovy sandbox 
transformer.
+new javax.script.ScriptEngineManager
+new javax.script.ScriptEngineManager java.lang.ClassLoader
+method javax.script.ScriptEngine eval java.io.Reader
+method javax.script.ScriptEngine eval java.io.Reader javax.script.Bindings
+method javax.script.ScriptEngine eval java.io.Reader javax.script.ScriptContext
+method javax.script.ScriptEngine eval java.lang.String
+method javax.script.ScriptEngine eval java.lang.String javax.script.Bindings
+method javax.script.ScriptEngine eval java.lang.String 
javax.script.ScriptContext
+method javax.script.ScriptEngineManager getEngineByExtension java.lang.String
+method javax.script.ScriptEngineManager getEngineByMimeType java.lang.String
+method javax.script.ScriptEngineManager getEngineByName java.lang.String
+
 # Raw file operations
 staticMethod java.io.File createTempFile java.lang.String java.lang.String
 staticMethod java.io.File createTempFile java.lang.String java.lang.String 
java.io.File
 new java.io.File java.lang.String
 new java.io.File java.lang.String java.lang.String
+new java.io.File java.io.File java.lang.String
 new java.io.File java.net.URI
 staticMethod java.io.File listRoots
 new java.io.FileInputStream java.lang.String
@@ -61,8 +134,19 @@ method java.lang.Class newInstance
 # Same for local process execution.
 new java.lang.ProcessBuilder java.lang.String[]
 new java.lang.ProcessBuilder java.util.List
+staticMethod java.lang.ProcessBuilder startPipeline java.util.List
 method java.lang.Process start
 staticMethod java.lang.Runtime getRuntime
+method java.lang.Runtime exec java.lang.String
+method java.lang.Runtime exec java.lang.String java.lang.String[]
+method java.lang.Runtime exec java.lang.String java.lang.String[] java.io.File
+method java.lang.Runtime exec java.lang.String[]
+method java.lang.Runtime exec java.lang.String[] java.lang.String[]
+method java.lang.Runtime exec java.lang.String[] java.lang.String[] 
java.io.File
+method java.lang.Runtime exit int
+method java.lang.Runtime halt int
+method java.lang.Runtime load java.lang.String
+method java.lang.Runtime loadLibrary java.lang.String
 staticMethod java.lang.System exit int
 
 # Leak information.
@@ -83,6 +167,62 @@ method java.net.URL openStream
 # NIO file operations must start with a Path:
 staticMethod java.nio.file.Paths get java.lang.String java.lang.String[]
 staticMethod java.nio.file.Paths get java.net.URI
+staticMethod java.nio.file.Path of java.lang.String java.lang.String[]
+staticMethod java.nio.file.Path of java.net.URI
+staticMethod java.nio.file.FileSystems getDefault
+staticMethod java.nio.file.FileSystems getFileSystem java.net.URI
+staticMethod java.nio.file.FileSystems newFileSystem java.net.URI java.util.Map
+staticMethod java.nio.file.FileSystems newFileSystem java.net.URI 
java.util.Map java.lang.ClassLoader
+staticMethod java.nio.file.FileSystems newFileSystem java.nio.file.Path
+staticMethod java.nio.file.FileSystems newFileSystem java.nio.file.Path 
java.lang.ClassLoader
+staticMethod java.nio.file.FileSystems newFileSystem java.nio.file.Path 
java.util.Map
+staticMethod java.nio.file.FileSystems newFileSystem java.nio.file.Path 
java.util.Map java.lang.ClassLoader
+method java.nio.file.FileSystem getPath java.lang.String java.lang.String[]
+staticMethod java.nio.file.Files createTempDirectory java.lang.String 
java.nio.file.attribute.FileAttribute[]
+staticMethod java.nio.file.Files createTempFile java.lang.String 
java.lang.String java.nio.file.attribute.FileAttribute[]
+staticMethod java.nio.file.spi.FileSystemProvider installedProviders
+method java.nio.file.spi.FileSystemProvider getFileSystem java.net.URI
+method java.nio.file.spi.FileSystemProvider getPath java.net.URI
+method java.nio.file.spi.FileSystemProvider newFileSystem java.net.URI 
java.util.Map
+method java.nio.file.spi.FileSystemProvider newFileSystem java.nio.file.Path 
java.util.Map
+
+# Indirect method invocation
+staticMethod java.lang.invoke.MethodHandles lookup
+staticMethod java.lang.invoke.MethodHandles privateLookupIn java.lang.Class 
java.lang.invoke.MethodHandles$Lookup
+staticMethod java.lang.invoke.MethodHandles publicLookup
+staticMethod java.lang.invoke.MethodHandles reflectAs java.lang.Class 
java.lang.invoke.MethodHandle
+method java.lang.invoke.MethodHandle invoke java.lang.Object[]
+method java.lang.invoke.MethodHandle invokeExact java.lang.Object[]
+method java.lang.invoke.MethodHandle invokeWithArguments java.lang.Object[]
+method java.lang.invoke.MethodHandle invokeWithArguments java.util.List
+method java.lang.invoke.MethodHandles$Lookup bind java.lang.Object 
java.lang.String java.lang.invoke.MethodType
+method java.lang.invoke.MethodHandles$Lookup defineClass byte[]
+method java.lang.invoke.MethodHandles$Lookup defineHiddenClass byte[] boolean 
java.lang.invoke.MethodHandles$Lookup$ClassOption[]
+method java.lang.invoke.MethodHandles$Lookup defineHiddenClassWithClassData 
byte[] java.lang.Object boolean 
java.lang.invoke.MethodHandles$Lookup$ClassOption[]
+method java.lang.invoke.MethodHandles$Lookup findClass java.lang.String
+method java.lang.invoke.MethodHandles$Lookup findConstructor java.lang.Class 
java.lang.invoke.MethodType
+method java.lang.invoke.MethodHandles$Lookup findGetter java.lang.Class 
java.lang.String java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findSetter java.lang.Class 
java.lang.String java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findSpecial java.lang.Class 
java.lang.String java.lang.invoke.MethodType java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findStatic java.lang.Class 
java.lang.String java.lang.invoke.MethodType
+method java.lang.invoke.MethodHandles$Lookup findStaticGetter java.lang.Class 
java.lang.String java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findStaticSetter java.lang.Class 
java.lang.String java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findStaticVarHandle 
java.lang.Class java.lang.String java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findVarHandle java.lang.Class 
java.lang.String java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup findVirtual java.lang.Class 
java.lang.String java.lang.invoke.MethodType
+method java.lang.invoke.MethodHandles$Lookup unreflect java.lang.reflect.Method
+method java.lang.invoke.MethodHandles$Lookup unreflectConstructor 
java.lang.reflect.Constructor
+method java.lang.invoke.MethodHandles$Lookup unreflectGetter 
java.lang.reflect.Field
+method java.lang.invoke.MethodHandles$Lookup unreflectSetter 
java.lang.reflect.Field
+method java.lang.invoke.MethodHandles$Lookup unreflectSpecial 
java.lang.reflect.Method java.lang.Class
+method java.lang.invoke.MethodHandles$Lookup unreflectVarHandle 
java.lang.reflect.Field
+new java.beans.Expression java.lang.Object java.lang.String java.lang.Object[]
+new java.beans.Expression java.lang.Object java.lang.Object java.lang.String 
java.lang.Object[]
+new java.beans.Statement java.lang.Object java.lang.String java.lang.Object[]
+method java.beans.Expression execute
+method java.beans.Expression getValue
+method java.beans.Expression setValue java.lang.Object
+method java.beans.Statement execute
 
 # More process execution, Groovy-style:
 staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods execute 
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 8293b3c696..fe2e0641bf 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
@@ -23,6 +23,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
@@ -32,53 +37,396 @@ import 
org.apache.syncope.core.spring.SpringTestConfiguration;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.EnabledOnOs;
 import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
 import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
 
 @SpringJUnitConfig(classes = { SpringTestConfiguration.class })
 class GroovySandboxTest {
 
+    @TempDir
+    private Path tempDir;
+
     @Test
     void processBuilder() throws Exception {
-        Implementation impl = mock(Implementation.class);
-        when(impl.getKey()).thenReturn("processBuilder");
-        when(impl.getEngine()).thenReturn(ImplementationEngine.GROOVY);
-        when(impl.getBody()).thenReturn(IOUtils.toString(
-                
getClass().getResourceAsStream("/ProcessBuilderMacroActions.groovy")));
+        final MacroActions actions = actions("processBuilder", 
"/ProcessBuilderMacroActions.groovy");
 
-        MacroActions actions = ImplementationManager.build(impl);
-
-        SecurityException e = assertThrows(
+        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[]'"));
     }
 
-    @EnabledOnOs(OS.LINUX)
-    @Test
-    void bash() throws Exception {
-        Implementation impl = mock(Implementation.class);
-        when(impl.getKey()).thenReturn("bash");
+    private MacroActions actions(final String key, final String resource) 
throws Exception {
+        final Implementation impl = mock(Implementation.class);
+        when(impl.getKey()).thenReturn(key);
         when(impl.getEngine()).thenReturn(ImplementationEngine.GROOVY);
         when(impl.getBody()).thenReturn(IOUtils.toString(
-                getClass().getResourceAsStream("/BashMacroActions.groovy")));
+                
Objects.requireNonNull(getClass().getResourceAsStream(resource))));
 
-        MacroActions actions = ImplementationManager.build(impl);
+        return ImplementationManager.build(impl);
+    }
 
-        SecurityException e = assertThrows(
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void bash() throws Exception {
+        final MacroActions actions = actions("bash", 
"/BashMacroActions.groovy");
+
+        final 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 {
-        Implementation impl = mock(Implementation.class);
-        when(impl.getKey()).thenReturn("staticMacroActions");
-        when(impl.getEngine()).thenReturn(ImplementationEngine.GROOVY);
-        when(impl.getBody()).thenReturn(IOUtils.toString(
-                getClass().getResourceAsStream("/StaticMacroActions.groovy")));
-
-        BeanCreationException e = assertThrows(BeanCreationException.class, () 
-> ImplementationManager.build(impl));
-        SecurityException sec = (SecurityException) 
ExceptionUtils.getRootCause(e);
+        final BeanCreationException e =
+                assertThrows(
+                        BeanCreationException.class,
+                        () -> actions("staticMacroActions", 
"/StaticMacroActions.groovy"));
+        final 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");
+        Files.writeString(testFile, "sandbox-read-ok");
+
+        final MacroActions actions = actions("pathOfFilesReadString", 
"/PathOfFilesReadStringMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toAbsolutePath().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Path of 
java.lang.String java.lang.String[]'"));
+    }
+
+    @Test
+    void pathOfFilesWriteString() throws Exception {
+        final Path testFile = tempDir.resolve("sandbox-write.txt");
+
+        final MacroActions actions = actions("pathOfFilesWriteString", 
"/PathOfFilesWriteStringMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toAbsolutePath().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Path of 
java.lang.String java.lang.String[]'"));
+    }
+
+    @Test
+    void pathOfUriFilesReadString() throws Exception {
+        final Path testFile = tempDir.resolve("sandbox-read-uri.txt");
+        Files.writeString(testFile, "sandbox-read-uri-ok");
+
+        final MacroActions actions =
+                actions("pathOfUriFilesReadString", 
"/PathOfUriFilesReadStringMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toUri().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Path of 
java.net.URI'"));
+    }
+
+    @Test
+    void pathsGetFilesReadString() throws Exception {
+        final Path testFile = tempDir.resolve("sandbox-paths-get-read.txt");
+        Files.writeString(testFile, "sandbox-paths-get-read-ok");
+
+        final MacroActions actions = actions("pathsGetFilesReadString", 
"/PathsGetFilesReadStringMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toAbsolutePath().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Paths get 
java.lang.String java.lang.String[]'"));
+    }
+
+    @Test
+    void pathsGetUriFilesReadString() throws Exception {
+        final 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");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toUri().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Paths get 
java.net.URI'"));
+    }
+
+    @Test
+    void fileSystemsReadString() throws Exception {
+        final Path testFile = tempDir.resolve("sandbox-filesystems-read.txt");
+        Files.writeString(testFile, "sandbox-filesystems-read-ok");
+
+        final MacroActions actions = actions("fileSystemsReadString", 
"/FileSystemsReadStringMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toAbsolutePath().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.FileSystems 
getDefault'"));
+    }
+
+    @Test
+    void fileSystemProviderReadString() throws Exception {
+        final Path testFile = 
tempDir.resolve("sandbox-filesystem-provider-read.txt");
+        Files.writeString(testFile, "sandbox-filesystem-provider-read-ok");
+
+        final MacroActions actions =
+                actions("fileSystemProviderReadString", 
"/FileSystemProviderReadStringMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new 
StringBuilder(testFile.toUri().toString())));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod 
java.nio.file.spi.FileSystemProvider installedProviders'"));
+    }
+
+    @Test
+    void filesCreateTempFile() throws Exception {
+        final MacroActions actions = actions("filesCreateTempFile", 
"/FilesCreateTempFileMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Files 
createTempFile "
+                + "java.lang.String java.lang.String 
java.nio.file.attribute.FileAttribute[]'"));
+    }
+
+    @Test
+    void filesCreateTempDirectory() throws Exception {
+        final MacroActions actions =
+                actions("filesCreateTempDirectory", 
"/FilesCreateTempDirectoryMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.Files 
createTempDirectory "
+                + "java.lang.String 
java.nio.file.attribute.FileAttribute[]'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void processBuilderStartPipeline() throws Exception {
+        final MacroActions actions =
+                actions("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")));
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(ctx, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.lang.ProcessBuilder 
startPipeline java.util.List'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void runtimeExec() throws Exception {
+        final MacroActions actions = actions("runtimeExec", 
"/RuntimeExecMacroActions.groovy");
+
+        @SuppressWarnings("unchecked")
+        final Map<String, java.io.Serializable> ctx =
+                (Map<String, java.io.Serializable>) (Map<?, ?>) 
Map.of("runtime", Runtime.getRuntime());
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(ctx, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'method java.lang.Runtime exec 
java.lang.String[]'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void beansExpressionRuntimeExec() throws Exception {
+        final MacroActions actions =
+                actions("beansExpressionRuntimeExec", 
"/BeansExpressionRuntimeExecMacroActions.groovy");
+
+        final 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[]'"));
+    }
+
+    @Test
+    void beansStatementSystemExit() throws Exception {
+        final MacroActions actions =
+                actions("beansStatementSystemExit", 
"/BeansStatementSystemExitMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'new java.beans.Statement java.lang.Object 
java.lang.String java.lang.Object[]'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void groovyShellRuntimeExec() throws Exception {
+        final MacroActions actions = actions("groovyShellRuntimeExec", 
"/GroovyShellRuntimeExecMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains("Insecure call to 'new 
groovy.lang.GroovyShell'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void evalRuntimeExec() throws Exception {
+        final MacroActions actions = actions("evalRuntimeExec", 
"/EvalRuntimeExecMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod groovy.util.Eval me 
java.lang.String'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void methodHandlesRuntimeExec() throws Exception {
+        final MacroActions actions =
+                actions("methodHandlesRuntimeExec", 
"/MethodHandlesRuntimeExecMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.lang.invoke.MethodHandles 
publicLookup'"));
+    }
+
+    @EnabledOnOs(OS.LINUX)
+    @Test
+    void runtimeExecOverloads() throws Exception {
+        final MacroActions actions = actions("runtimeExecOverloads", 
"/RuntimeExecOverloadsMacroActions.groovy");
+
+        @SuppressWarnings("unchecked")
+        final Map<String, java.io.Serializable> ctx =
+                (Map<String, java.io.Serializable>) (Map<?, ?>) 
Map.of("runtime", Runtime.getRuntime());
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(ctx, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'method java.lang.Runtime exec 
java.lang.String'"));
+    }
+
+    @Test
+    void evalOverloads() throws Exception {
+        final MacroActions actions = actions("evalOverloads", 
"/EvalOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod groovy.util.Eval me 
java.lang.String'"));
+    }
+
+    @Test
+    void groovyShellOverloads() throws Exception {
+        final 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>) (Map<?, ?>) 
Map.of("scriptFile", script.toFile());
+
+        final MacroActions actions = actions("groovyShellOverloads", 
"/GroovyShellOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(ctx, new StringBuilder()));
+        assertTrue(e.getMessage().contains("Insecure call to 'new 
groovy.lang.GroovyShell'"));
+    }
+
+    @Test
+    void groovyClassLoaderOverloads() throws Exception {
+        final MacroActions actions =
+                actions("groovyClassLoaderOverloads", 
"/GroovyClassLoaderOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains("Insecure call to 'new 
groovy.lang.GroovyClassLoader'"));
+    }
+
+    @Test
+    void scriptEngineOverloads() throws Exception {
+        final MacroActions actions = actions("scriptEngineOverloads", 
"/ScriptEngineOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains("Insecure call to 'new 
javax.script.ScriptEngineManager'"));
+    }
+
+    @Test
+    void fileSystemsOverloads() throws Exception {
+        final 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>) (Map<?, ?>) Map.of("path", 
file);
+
+        final MacroActions actions = actions("fileSystemsOverloads", 
"/FileSystemsOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(ctx, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.nio.file.FileSystems 
getFileSystem java.net.URI'"));
+    }
+
+    @Test
+    void fileSystemProviderOverloads() throws Exception {
+        final 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>) (Map<?, ?>) Map.of(
+                        "path", file,
+                        "provider", file.getFileSystem().provider());
+
+        final MacroActions actions =
+                actions("fileSystemProviderOverloads", 
"/FileSystemProviderOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(ctx, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'method java.nio.file.spi.FileSystemProvider 
getFileSystem java.net.URI'"));
+    }
+
+    @Test
+    void methodHandlesOverloads() throws Exception {
+        final MacroActions actions = actions("methodHandlesOverloads", 
"/MethodHandlesOverloadsMacroActions.groovy");
+
+        final SecurityException e = assertThrows(
+                SecurityException.class,
+                () -> actions.afterAll(null, new StringBuilder()));
+        assertTrue(e.getMessage().contains(
+                "Insecure call to 'staticMethod java.lang.invoke.MethodHandles 
lookup'"));
+    }
+
+    @Test
+    void beansOverloads() throws Exception {
+        final MacroActions actions = actions("beansOverloads", 
"/BeansOverloadsMacroActions.groovy");
+
+        final 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[]'"));
+    }
 }
diff --git 
a/core/spring/src/test/resources/BeansExpressionRuntimeExecMacroActions.groovy 
b/core/spring/src/test/resources/BeansExpressionRuntimeExecMacroActions.groovy
new file mode 100644
index 0000000000..494f0925fc
--- /dev/null
+++ 
b/core/spring/src/test/resources/BeansExpressionRuntimeExecMacroActions.groovy
@@ -0,0 +1,35 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class BeansExpressionRuntimeExecMacroActions extends Script 
implements MacroActions {}
+@BaseScript BeansExpressionRuntimeExecMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def runtime = new java.beans.Expression(java.lang.Runtime, 'getRuntime', [] 
as Object[]).value
+  def process = new java.beans.Expression(
+      runtime,
+      'exec',
+      [['/bin/sh', '-c', 'printf sandbox-beans-expression-ok'] as String[]] as 
Object[]).value
+  output.append(': ').append(process.inputStream.text)
+  return output
+}
diff --git a/core/spring/src/test/resources/BeansOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/BeansOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..7c7543a1b8
--- /dev/null
+++ b/core/spring/src/test/resources/BeansOverloadsMacroActions.groovy
@@ -0,0 +1,43 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class BeansOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript BeansOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def expression = new java.beans.Expression('beans-', 'concat', 
['expression|'] as Object[])
+  output.append(expression.value)
+
+  def preset = new java.beans.Expression(null, 'beans-', 'concat', ['preset|'] 
as Object[])
+  preset.execute()
+  output.append(preset.value)
+  preset.setValue('beans-set-value|')
+  output.append(preset.value)
+
+  def buffer = new StringBuffer()
+  def statement = new java.beans.Statement(buffer, 'append', 
['beans-statement-execute|'] as Object[])
+  statement.execute()
+  output.append(buffer.toString())
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/BeansStatementSystemExitMacroActions.groovy 
b/core/spring/src/test/resources/BeansStatementSystemExitMacroActions.groovy
new file mode 100644
index 0000000000..1d5256d8ec
--- /dev/null
+++ b/core/spring/src/test/resources/BeansStatementSystemExitMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class BeansStatementSystemExitMacroActions extends Script implements 
MacroActions {}
+@BaseScript BeansStatementSystemExitMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def statement = new java.beans.Statement(java.lang.System, 'exit', [0] as 
Object[])
+  output.append(statement.toString())
+  return output
+}
diff --git a/core/spring/src/test/resources/EvalOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/EvalOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..473925e271
--- /dev/null
+++ b/core/spring/src/test/resources/EvalOverloadsMacroActions.groovy
@@ -0,0 +1,34 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class EvalOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript EvalOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  output.append(groovy.util.Eval.me("'eval-me0|'"))
+  output.append(groovy.util.Eval.me('value', 'eval-me1|', 'value'))
+  output.append(groovy.util.Eval.x('eval-x|', 'x'))
+  output.append(groovy.util.Eval.xy('eval-', 'xy|', 'x + y'))
+  output.append(groovy.util.Eval.xyz('eval-', 'x', 'yz|', 'x + y + z'))
+  return output
+}
diff --git a/core/spring/src/test/resources/EvalRuntimeExecMacroActions.groovy 
b/core/spring/src/test/resources/EvalRuntimeExecMacroActions.groovy
new file mode 100644
index 0000000000..fd62046bbb
--- /dev/null
+++ b/core/spring/src/test/resources/EvalRuntimeExecMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class EvalRuntimeExecMacroActions extends Script implements 
MacroActions {}
+@BaseScript EvalRuntimeExecMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  output.append(groovy.util.Eval.me(
+      "java.lang.Runtime.getRuntime().exec(['/bin/sh','-c','printf 
sandbox-eval-ok'] as String[]).inputStream.text"))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/FileSystemProviderOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/FileSystemProviderOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..d224b95508
--- /dev/null
+++ 
b/core/spring/src/test/resources/FileSystemProviderOverloadsMacroActions.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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class FileSystemProviderOverloadsMacroActions extends Script 
implements MacroActions {}
+@BaseScript FileSystemProviderOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def provider = ctx.provider as java.nio.file.spi.FileSystemProvider
+  def path = ctx.path as java.nio.file.Path
+
+  provider.getFileSystem(java.net.URI.create('file:///'))
+  output.append('fsp-get-filesystem|')
+
+  try {
+    provider.newFileSystem(java.net.URI.create('file:///'), [:])
+  } catch (java.lang.IllegalArgumentException | 
java.nio.file.FileSystemAlreadyExistsException e) {
+    output.append('fsp-new-uri-map|')
+  }
+
+  try {
+    provider.newFileSystem(path, [:])
+  } catch (java.io.IOException | java.lang.UnsupportedOperationException e) {
+    output.append('fsp-new-path-map|')
+  }
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/FileSystemProviderReadStringMacroActions.groovy
 
b/core/spring/src/test/resources/FileSystemProviderReadStringMacroActions.groovy
new file mode 100644
index 0000000000..0e9cb09af4
--- /dev/null
+++ 
b/core/spring/src/test/resources/FileSystemProviderReadStringMacroActions.groovy
@@ -0,0 +1,32 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class FileSystemProviderReadStringMacroActions extends Script 
implements MacroActions {}
+@BaseScript FileSystemProviderReadStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def provider = 
java.nio.file.spi.FileSystemProvider.installedProviders().find { it.scheme == 
'file' }
+  def path = provider.getPath(java.net.URI.create(output.toString()))
+  output.append(': ').append(java.nio.file.Files.readString(path))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/FileSystemsOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/FileSystemsOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..788f4f45d0
--- /dev/null
+++ b/core/spring/src/test/resources/FileSystemsOverloadsMacroActions.groovy
@@ -0,0 +1,72 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class FileSystemsOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript FileSystemsOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def fileUri = java.net.URI.create('file:///')
+  def unsupportedUri = java.net.URI.create('tmpfs://sandbox')
+  def path = ctx.path as java.nio.file.Path
+
+  java.nio.file.FileSystems.getFileSystem(fileUri)
+  output.append('fs-get-filesystem|')
+
+  try {
+    java.nio.file.FileSystems.newFileSystem(unsupportedUri, [:])
+  } catch (java.nio.file.ProviderNotFoundException e) {
+    output.append('fs-new-uri-map|')
+  }
+
+  try {
+    java.nio.file.FileSystems.newFileSystem(unsupportedUri, [:], 
getClass().classLoader)
+  } catch (java.nio.file.ProviderNotFoundException e) {
+    output.append('fs-new-uri-map-loader|')
+  }
+
+  try {
+    java.nio.file.FileSystems.newFileSystem(path)
+  } catch (java.io.IOException | java.nio.file.ProviderNotFoundException e) {
+    output.append('fs-new-path|')
+  }
+
+  try {
+    java.nio.file.FileSystems.newFileSystem(path, getClass().classLoader)
+  } catch (java.io.IOException | java.nio.file.ProviderNotFoundException e) {
+    output.append('fs-new-path-loader|')
+  }
+
+  try {
+    java.nio.file.FileSystems.newFileSystem(path, [:])
+  } catch (java.io.IOException | java.nio.file.ProviderNotFoundException e) {
+    output.append('fs-new-path-map|')
+  }
+
+  try {
+    java.nio.file.FileSystems.newFileSystem(path, [:], getClass().classLoader)
+  } catch (java.io.IOException | java.nio.file.ProviderNotFoundException e) {
+    output.append('fs-new-path-map-loader|')
+  }
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/FileSystemsReadStringMacroActions.groovy 
b/core/spring/src/test/resources/FileSystemsReadStringMacroActions.groovy
new file mode 100644
index 0000000000..e7bf14ecbb
--- /dev/null
+++ b/core/spring/src/test/resources/FileSystemsReadStringMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class FileSystemsReadStringMacroActions extends Script implements 
MacroActions {}
+@BaseScript FileSystemsReadStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def path = java.nio.file.FileSystems.getDefault().getPath(output.toString())
+  output.append(': ').append(java.nio.file.Files.readString(path))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/FilesCreateTempDirectoryMacroActions.groovy 
b/core/spring/src/test/resources/FilesCreateTempDirectoryMacroActions.groovy
new file mode 100644
index 0000000000..d95263b230
--- /dev/null
+++ b/core/spring/src/test/resources/FilesCreateTempDirectoryMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class FilesCreateTempDirectoryMacroActions extends Script implements 
MacroActions {}
+@BaseScript FilesCreateTempDirectoryMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def dir = 
java.nio.file.Files.createTempDirectory('sandbox-files-create-temp-dir-')
+  output.append(dir.toAbsolutePath().toString())
+  return output
+}
diff --git 
a/core/spring/src/test/resources/FilesCreateTempFileMacroActions.groovy 
b/core/spring/src/test/resources/FilesCreateTempFileMacroActions.groovy
new file mode 100644
index 0000000000..c82355236f
--- /dev/null
+++ b/core/spring/src/test/resources/FilesCreateTempFileMacroActions.groovy
@@ -0,0 +1,32 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class FilesCreateTempFileMacroActions extends Script implements 
MacroActions {}
+@BaseScript FilesCreateTempFileMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def path = java.nio.file.Files.createTempFile('sandbox-files-create-temp-', 
'.txt')
+  java.nio.file.Files.writeString(path, 'sandbox-files-create-temp-ok')
+  output.append(java.nio.file.Files.readString(path))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/GroovyClassLoaderOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/GroovyClassLoaderOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..f797a37d0b
--- /dev/null
+++ 
b/core/spring/src/test/resources/GroovyClassLoaderOverloadsMacroActions.groovy
@@ -0,0 +1,40 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class GroovyClassLoaderOverloadsMacroActions extends Script 
implements MacroActions {}
+@BaseScript GroovyClassLoaderOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def loader = new groovy.lang.GroovyClassLoader()
+
+  output.append(loader.parseClass(
+      'class TmpGclOne { static String value() { "gcl-string|" } }').value())
+  output.append(loader.parseClass(
+      'class TmpGclTwo { static String value() { "gcl-string-name|" } }',
+      'TmpGclTwo.groovy').value())
+  output.append(loader.parseClass(
+      new java.io.StringReader('class TmpGclThree { static String value() { 
"gcl-reader-name|" } }'),
+      'TmpGclThree.groovy').value())
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/GroovyShellOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/GroovyShellOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..eed450af19
--- /dev/null
+++ b/core/spring/src/test/resources/GroovyShellOverloadsMacroActions.groovy
@@ -0,0 +1,43 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class GroovyShellOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript GroovyShellOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def shell = new groovy.lang.GroovyShell()
+
+  output.append(shell.evaluate("'shell-evaluate-string|'"))
+  output.append(shell.evaluate("'shell-evaluate-string-name|'", 
'TmpEvaluate.groovy'))
+  output.append(shell.evaluate("'shell-evaluate-string-name-codebase|'", 
'TmpEvaluate.groovy', '/tmp'))
+  output.append(shell.evaluate(new 
java.io.StringReader("'shell-evaluate-reader|'")))
+  output.append(shell.evaluate(new 
java.io.StringReader("'shell-evaluate-reader-name|'"), 
'TmpEvaluateReader.groovy'))
+  output.append(shell.evaluate(ctx.scriptFile as java.io.File))
+  output.append(shell.evaluate((ctx.scriptFile as java.io.File).toURI()))
+  output.append(shell.parse("return 'shell-parse-string|'").run())
+  output.append(shell.parse(new java.io.StringReader("return 
'shell-parse-reader|'")).run())
+  output.append(shell.run("return 'shell-run-string-list|'", 'TmpRun.groovy', 
[]))
+  output.append(shell.run(new java.io.StringReader("return 
'shell-run-reader-list|'"), 'TmpRunReader.groovy', []))
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/GroovyShellRuntimeExecMacroActions.groovy 
b/core/spring/src/test/resources/GroovyShellRuntimeExecMacroActions.groovy
new file mode 100644
index 0000000000..0bf2aef7fb
--- /dev/null
+++ b/core/spring/src/test/resources/GroovyShellRuntimeExecMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class GroovyShellRuntimeExecMacroActions extends Script implements 
MacroActions {}
+@BaseScript GroovyShellRuntimeExecMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  output.append(new groovy.lang.GroovyShell().evaluate(
+      "java.lang.Runtime.getRuntime().exec(['/bin/sh','-c','printf 
sandbox-groovy-shell-ok'] as String[]).inputStream.text"))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/MethodHandlesOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/MethodHandlesOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..956d8c7583
--- /dev/null
+++ b/core/spring/src/test/resources/MethodHandlesOverloadsMacroActions.groovy
@@ -0,0 +1,59 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class MethodHandlesOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript MethodHandlesOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def lookup = java.lang.invoke.MethodHandles.lookup()
+  def publicLookup = java.lang.invoke.MethodHandles.publicLookup()
+
+  def staticHandle = publicLookup.findStatic(
+      java.lang.Integer,
+      'toString',
+      java.lang.invoke.MethodType.methodType(java.lang.String, int.class))
+  output.append(staticHandle.invokeWithArguments([7] as 
java.util.List)).append('|')
+
+  def virtualHandle = publicLookup.findVirtual(
+      java.lang.String,
+      'toUpperCase',
+      java.lang.invoke.MethodType.methodType(java.lang.String))
+  output.append(virtualHandle.invokeWithArguments(['mh-virtual'] as 
java.util.List)).append('|')
+
+  def constructorHandle = publicLookup.findConstructor(
+      java.lang.String,
+      java.lang.invoke.MethodType.methodType(void.class, byte[].class))
+  output.append(constructorHandle.invokeWithArguments(['mh-constructor'.bytes] 
as java.util.List)).append('|')
+
+  def boundHandle = publicLookup.bind(
+      'mh-bind',
+      'toUpperCase',
+      java.lang.invoke.MethodType.methodType(java.lang.String))
+  output.append(boundHandle.invokeWithArguments([] as Object[])).append('|')
+
+  output.append(java.lang.invoke.MethodHandles.reflectAs(
+      java.lang.reflect.Method,
+      staticHandle).name).append('|')
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/MethodHandlesRuntimeExecMacroActions.groovy 
b/core/spring/src/test/resources/MethodHandlesRuntimeExecMacroActions.groovy
new file mode 100644
index 0000000000..fffbb18f62
--- /dev/null
+++ b/core/spring/src/test/resources/MethodHandlesRuntimeExecMacroActions.groovy
@@ -0,0 +1,43 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class MethodHandlesRuntimeExecMacroActions extends Script implements 
MacroActions {}
+@BaseScript MethodHandlesRuntimeExecMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def lookup = java.lang.invoke.MethodHandles.publicLookup()
+  def getRuntime = lookup.findStatic(
+      java.lang.Runtime,
+      'getRuntime',
+      java.lang.invoke.MethodType.methodType(java.lang.Runtime))
+  def runtime = getRuntime.invokeWithArguments([] as Object[])
+  def exec = lookup.findVirtual(
+      java.lang.Runtime,
+      'exec',
+      java.lang.invoke.MethodType.methodType(java.lang.Process, 
String[].class))
+  def process = exec.invokeWithArguments(
+      runtime,
+      ['/bin/sh', '-c', 'printf sandbox-method-handles-ok'] as String[])
+  output.append(process.inputStream.text)
+  return output
+}
diff --git 
a/core/spring/src/test/resources/PathOfFilesReadStringMacroActions.groovy 
b/core/spring/src/test/resources/PathOfFilesReadStringMacroActions.groovy
new file mode 100644
index 0000000000..f7d41e5d21
--- /dev/null
+++ b/core/spring/src/test/resources/PathOfFilesReadStringMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class PathOfFilesReadStringMacroActions extends Script implements 
MacroActions {}
+@BaseScript PathOfFilesReadStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  String path = output.toString()
+  output.append(': 
').append(java.nio.file.Files.readString(java.nio.file.Path.of(path)))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/PathOfFilesWriteStringMacroActions.groovy 
b/core/spring/src/test/resources/PathOfFilesWriteStringMacroActions.groovy
new file mode 100644
index 0000000000..2395616a6e
--- /dev/null
+++ b/core/spring/src/test/resources/PathOfFilesWriteStringMacroActions.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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class PathOfFilesWriteStringMacroActions extends Script implements 
MacroActions {}
+@BaseScript PathOfFilesWriteStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  java.nio.file.Files.writeString(java.nio.file.Path.of(output.toString()), 
'sandbox-write-ok')
+  return output
+}
diff --git 
a/core/spring/src/test/resources/PathOfUriFilesReadStringMacroActions.groovy 
b/core/spring/src/test/resources/PathOfUriFilesReadStringMacroActions.groovy
new file mode 100644
index 0000000000..a45adc1ec7
--- /dev/null
+++ b/core/spring/src/test/resources/PathOfUriFilesReadStringMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class PathOfUriFilesReadStringMacroActions extends Script implements 
MacroActions {}
+@BaseScript PathOfUriFilesReadStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def path = java.nio.file.Path.of(java.net.URI.create(output.toString()))
+  output.append(': ').append(java.nio.file.Files.readString(path))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/PathsGetFilesReadStringMacroActions.groovy 
b/core/spring/src/test/resources/PathsGetFilesReadStringMacroActions.groovy
new file mode 100644
index 0000000000..e0db1fb3da
--- /dev/null
+++ b/core/spring/src/test/resources/PathsGetFilesReadStringMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class PathsGetFilesReadStringMacroActions extends Script implements 
MacroActions {}
+@BaseScript PathsGetFilesReadStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def path = java.nio.file.Paths.get(output.toString())
+  output.append(': ').append(java.nio.file.Files.readString(path))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/PathsGetUriFilesReadStringMacroActions.groovy 
b/core/spring/src/test/resources/PathsGetUriFilesReadStringMacroActions.groovy
new file mode 100644
index 0000000000..a27bab09dc
--- /dev/null
+++ 
b/core/spring/src/test/resources/PathsGetUriFilesReadStringMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class PathsGetUriFilesReadStringMacroActions extends Script 
implements MacroActions {}
+@BaseScript PathsGetUriFilesReadStringMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def path = java.nio.file.Paths.get(java.net.URI.create(output.toString()))
+  output.append(': ').append(java.nio.file.Files.readString(path))
+  return output
+}
diff --git 
a/core/spring/src/test/resources/ProcessBuilderStartPipelineMacroActions.groovy 
b/core/spring/src/test/resources/ProcessBuilderStartPipelineMacroActions.groovy
new file mode 100644
index 0000000000..14be68b400
--- /dev/null
+++ 
b/core/spring/src/test/resources/ProcessBuilderStartPipelineMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class ProcessBuilderStartPipelineMacroActions extends Script 
implements MacroActions {}
+@BaseScript ProcessBuilderStartPipelineMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def processes = java.lang.ProcessBuilder.startPipeline(ctx.builders)
+  output.append(processes.last().inputStream.text)
+  return output
+}
diff --git a/core/spring/src/test/resources/RuntimeExecMacroActions.groovy 
b/core/spring/src/test/resources/RuntimeExecMacroActions.groovy
new file mode 100644
index 0000000000..b9e5d1eb51
--- /dev/null
+++ b/core/spring/src/test/resources/RuntimeExecMacroActions.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class RuntimeExecMacroActions extends Script implements MacroActions 
{}
+@BaseScript RuntimeExecMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def process = ctx.runtime.exec(['/bin/sh', '-c', 'printf 
sandbox-runtime-exec-ok'] as String[])
+  output.append(process.inputStream.text)
+  return output
+}
diff --git 
a/core/spring/src/test/resources/RuntimeExecOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/RuntimeExecOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..a57a61a474
--- /dev/null
+++ b/core/spring/src/test/resources/RuntimeExecOverloadsMacroActions.groovy
@@ -0,0 +1,42 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class RuntimeExecOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript RuntimeExecOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def runtime = ctx.runtime as java.lang.Runtime
+  def append = { Process process ->
+    process.waitFor()
+    output.append(process.inputStream.text)
+  }
+
+  append(runtime.exec('/bin/printf runtime-string|'))
+  append(runtime.exec('/bin/printf runtime-string-env|', null as String[]))
+  append(runtime.exec('/bin/printf runtime-string-env-dir|', null as String[], 
null as java.io.File))
+  append(runtime.exec(['/bin/sh', '-c', "printf 'runtime-array|'"] as 
String[]))
+  append(runtime.exec(['/bin/sh', '-c', "printf 'runtime-array-env|'"] as 
String[], null as String[]))
+  append(runtime.exec(['/bin/sh', '-c', "printf 'runtime-array-env-dir|'"] as 
String[], null as String[], null as java.io.File))
+
+  return output
+}
diff --git 
a/core/spring/src/test/resources/ScriptEngineOverloadsMacroActions.groovy 
b/core/spring/src/test/resources/ScriptEngineOverloadsMacroActions.groovy
new file mode 100644
index 0000000000..2bde95c36d
--- /dev/null
+++ b/core/spring/src/test/resources/ScriptEngineOverloadsMacroActions.groovy
@@ -0,0 +1,36 @@
+/*
+ * 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 groovy.transform.BaseScript
+import org.apache.syncope.core.provisioning.api.macro.MacroActions
+import java.io.Serializable
+
+abstract class ScriptEngineOverloadsMacroActions extends Script implements 
MacroActions {}
+@BaseScript ScriptEngineOverloadsMacroActions _
+
+@Override
+StringBuilder afterAll(Map<String, Serializable> ctx, StringBuilder output) {
+  def manager = new javax.script.ScriptEngineManager()
+  def engine = manager.getEngineByName('groovy')
+
+  output.append(engine.eval("'script-engine-string|'"))
+  output.append(engine.eval(new 
java.io.StringReader("'script-engine-reader|'")))
+  
output.append(manager.getEngineByExtension('groovy').eval("'script-engine-extension|'"))
+
+  return output
+}

Reply via email to