GraalVM Polyglot API for embedding multiple programming languages in Java applications with secure language interoperability
—
Security configuration provides comprehensive access control and sandboxing for polyglot environments. It enables fine-grained control over host system access, cross-language interactions, resource consumption, and environment isolation.
Configure access to host (Java) objects from guest languages.
public final class HostAccess {
public static final HostAccess ALL;
public static final HostAccess EXPLICIT;
public static final HostAccess NONE;
public static final HostAccess SCOPED;
public static HostAccess.Builder newBuilder();
public static HostAccess.Builder newBuilder(HostAccess conf);
}
public static final class HostAccess.Builder {
public HostAccess.Builder allowPublicAccess(boolean enabled);
public HostAccess.Builder allowAllImplementations(boolean enabled);
public HostAccess.Builder allowAllClassImplementations(boolean enabled);
public HostAccess.Builder allowArrayAccess(boolean enabled);
public HostAccess.Builder allowListAccess(boolean enabled);
public HostAccess.Builder allowBufferAccess(boolean enabled);
public HostAccess.Builder allowIterableAccess(boolean enabled);
public HostAccess.Builder allowIteratorAccess(boolean enabled);
public HostAccess.Builder allowMapAccess(boolean enabled);
public HostAccess.Builder allowAccessAnnotatedBy(Class<? extends Annotation> annotation);
public HostAccess.Builder allowImplementationsAnnotatedBy(Class<? extends Annotation> annotation);
public HostAccess.Builder denyAccess(Class<?> clazz);
public HostAccess.Builder allowAccess(Class<?> clazz);
public HostAccess.Builder allowAccess(Method method);
public HostAccess.Builder allowAccess(Field field);
public HostAccess.Builder allowAccess(Constructor<?> constructor);
public HostAccess.Builder targetTypeMapping(Class<?> sourceType, Class<?> targetType, Predicate<Object> accepts, Function<Object, Object> converter);
public HostAccess build();
}Usage:
// Predefined configurations
Context allAccess = Context.newBuilder("js")
.allowHostAccess(HostAccess.ALL) // Allow all host access
.build();
Context explicitAccess = Context.newBuilder("js")
.allowHostAccess(HostAccess.EXPLICIT) // Only @HostAccess.Export annotated
.build();
Context noAccess = Context.newBuilder("js")
.allowHostAccess(HostAccess.NONE) // No host access
.build();
Context scopedAccess = Context.newBuilder("js")
.allowHostAccess(HostAccess.SCOPED) // Scoped access
.build();
// Custom configuration
HostAccess customAccess = HostAccess.newBuilder()
.allowPublicAccess(true)
.allowArrayAccess(true)
.allowListAccess(true)
.allowMapAccess(false)
.allowAccess(MyPublicClass.class)
.denyAccess(MySensitiveClass.class)
.allowAccessAnnotatedBy(HostAccess.Export.class)
.build();
Context customContext = Context.newBuilder("js")
.allowHostAccess(customAccess)
.build();Configure cross-language access between guest languages.
public final class PolyglotAccess {
public static final PolyglotAccess ALL;
public static final PolyglotAccess NONE;
public static PolyglotAccess.Builder newBuilder();
}
public static final class PolyglotAccess.Builder {
public PolyglotAccess.Builder allowEval(String languageId, String... targetLanguageIds);
public PolyglotAccess.Builder allowBindingsAccess(String languageId);
public PolyglotAccess.Builder denyBindingsAccess(String languageId);
public PolyglotAccess.Builder allowEvalBetween(String... languageIds);
public PolyglotAccess build();
}Usage:
// Allow all cross-language access
Context allPolyglot = Context.newBuilder("js", "python")
.allowPolyglotAccess(PolyglotAccess.ALL)
.build();
// Deny all cross-language access
Context noPolyglot = Context.newBuilder("js", "python")
.allowPolyglotAccess(PolyglotAccess.NONE)
.build();
// Custom polyglot access
PolyglotAccess customPolyglot = PolyglotAccess.newBuilder()
.allowEval("js", "python") // JS can eval Python
.allowBindingsAccess("js") // JS can access bindings
.denyBindingsAccess("python") // Python cannot access bindings
.allowEvalBetween("js", "python", "R") // Mutual eval between languages
.build();
Context customContext = Context.newBuilder("js", "python", "R")
.allowPolyglotAccess(customPolyglot)
.build();Configure file system, network, and process access.
public final class IOAccess {
public static final IOAccess ALL;
public static final IOAccess NONE;
public static IOAccess.Builder newBuilder();
}
public static final class IOAccess.Builder {
public IOAccess.Builder allowHostFileAccess(boolean enabled);
public IOAccess.Builder allowHostSocketAccess(boolean enabled);
public IOAccess.Builder fileSystem(FileSystem fileSystem);
public IOAccess.Builder processHandler(ProcessHandler processHandler);
public IOAccess build();
}Usage:
// Allow all I/O
Context allIO = Context.newBuilder("js")
.allowIO(IOAccess.ALL)
.build();
// Deny all I/O
Context noIO = Context.newBuilder("js")
.allowIO(IOAccess.NONE)
.build();
// Custom I/O access
FileSystem restrictedFS = new RestrictedFileSystem("/safe/directory");
ProcessHandler restrictedProc = new RestrictedProcessHandler();
IOAccess customIO = IOAccess.newBuilder()
.allowHostFileAccess(false) // No direct file access
.allowHostSocketAccess(false) // No socket access
.fileSystem(restrictedFS) // Custom file system
.processHandler(restrictedProc) // Custom process handler
.build();
Context customContext = Context.newBuilder("js")
.allowIO(customIO)
.build();Apply predefined security policies for different trust levels.
public enum SandboxPolicy {
TRUSTED, // No restrictions
CONSTRAINED, // Limited restrictions
ISOLATED, // Strong restrictions
UNTRUSTED // Maximum restrictions
}Usage:
// Trusted environment (no restrictions)
Context trusted = Context.newBuilder("js")
.sandbox(SandboxPolicy.TRUSTED)
.build();
// Constrained environment
Context constrained = Context.newBuilder("js")
.sandbox(SandboxPolicy.CONSTRAINED)
.build();
// Isolated environment
Context isolated = Context.newBuilder("js")
.sandbox(SandboxPolicy.ISOLATED)
.build();
// Untrusted environment (maximum restrictions)
Context untrusted = Context.newBuilder("js")
.sandbox(SandboxPolicy.UNTRUSTED)
.build();Control resource consumption and execution limits.
public final class ResourceLimits {
public static ResourceLimits.Builder newBuilder();
}
public static final class ResourceLimits.Builder {
public ResourceLimits.Builder statementLimit(long limit, Predicate<Source> sourceFilter);
public ResourceLimits.Builder onLimit(Consumer<ResourceLimitEvent> onLimit);
public ResourceLimits build();
}
public final class ResourceLimitEvent {
public String getLimit();
public Context getContext();
}Usage:
// Statement execution limit
ResourceLimits limits = ResourceLimits.newBuilder()
.statementLimit(10000, source -> !source.isInternal())
.onLimit(event -> {
System.out.println("Resource limit exceeded: " + event.getLimit());
// Handle limit exceeded
})
.build();
Context limitedContext = Context.newBuilder("js")
.resourceLimits(limits)
.build();
try {
// This will hit the statement limit
limitedContext.eval("js", "while(true) { /* infinite loop */ }");
} catch (PolyglotException e) {
if (e.isResourceExhausted()) {
System.out.println("Resource limit reached");
}
}Control access to environment variables and system properties.
public final class EnvironmentAccess {
public static final EnvironmentAccess INHERIT;
public static final EnvironmentAccess NONE;
public static EnvironmentAccess.Builder newBuilder();
}
public static final class EnvironmentAccess.Builder {
public EnvironmentAccess.Builder inheritSystemProperties(boolean enabled);
public EnvironmentAccess.Builder inheritEnvironmentVariables(boolean enabled);
public EnvironmentAccess build();
}Usage:
// Inherit all environment
Context inheritEnv = Context.newBuilder("js")
.allowEnvironmentAccess(EnvironmentAccess.INHERIT)
.build();
// No environment access
Context noEnv = Context.newBuilder("js")
.allowEnvironmentAccess(EnvironmentAccess.NONE)
.build();
// Custom environment access
EnvironmentAccess customEnv = EnvironmentAccess.newBuilder()
.inheritSystemProperties(false)
.inheritEnvironmentVariables(true)
.build();
Context customContext = Context.newBuilder("js")
.allowEnvironmentAccess(customEnv)
.build();Combine multiple security mechanisms for defense in depth:
Context secureContext = Context.newBuilder("js")
.sandbox(SandboxPolicy.ISOLATED)
.allowHostAccess(HostAccess.EXPLICIT)
.allowPolyglotAccess(PolyglotAccess.NONE)
.allowIO(IOAccess.NONE)
.allowEnvironmentAccess(EnvironmentAccess.NONE)
.allowCreateThread(false)
.allowNativeAccess(false)
.resourceLimits(ResourceLimits.newBuilder()
.statementLimit(100000, null)
.build())
.build();Create fine-grained host access controls:
@HostAccess.Export
public class SafeAPI {
@HostAccess.Export
public String processData(String data) {
// Safe data processing
return data.toUpperCase();
}
// This method is not exported (no annotation)
private void sensitiveOperation() {
// Not accessible from guest languages
}
}
HostAccess restrictedAccess = HostAccess.newBuilder()
.allowAccessAnnotatedBy(HostAccess.Export.class)
.allowAccess(String.class)
.allowAccess(Integer.class)
.denyAccess(System.class)
.denyAccess(Runtime.class)
.build();
Context restrictedContext = Context.newBuilder("js")
.allowHostAccess(restrictedAccess)
.build();
restrictedContext.getBindings("js").putMember("api", new SafeAPI());
restrictedContext.eval("js", "api.processData('hello')"); // Works
// restrictedContext.eval("js", "api.sensitiveOperation()"); // FailsMonitor and respond to security events:
ResourceLimits monitoredLimits = ResourceLimits.newBuilder()
.statementLimit(50000, null)
.onLimit(event -> {
// Log security event
logger.warn("Resource limit exceeded in context: " + event.getContext());
// Take corrective action
event.getContext().interrupt(Duration.ofSeconds(1));
})
.build();
Context monitoredContext = Context.newBuilder("js")
.resourceLimits(monitoredLimits)
.build();Create reusable security configurations:
public class SecurityConfigurations {
public static Context.Builder webSandbox() {
return Context.newBuilder()
.sandbox(SandboxPolicy.ISOLATED)
.allowHostAccess(HostAccess.EXPLICIT)
.allowPolyglotAccess(PolyglotAccess.NONE)
.allowIO(IOAccess.NONE)
.allowEnvironmentAccess(EnvironmentAccess.NONE)
.allowCreateThread(false);
}
public static Context.Builder trustedScript() {
return Context.newBuilder()
.sandbox(SandboxPolicy.CONSTRAINED)
.allowHostAccess(HostAccess.ALL)
.allowPolyglotAccess(PolyglotAccess.ALL)
.allowIO(IOAccess.ALL);
}
public static Context.Builder dataProcessing() {
return Context.newBuilder()
.sandbox(SandboxPolicy.CONSTRAINED)
.allowHostAccess(HostAccess.newBuilder()
.allowPublicAccess(true)
.allowArrayAccess(true)
.allowListAccess(true)
.denyAccess(System.class)
.build())
.allowIO(IOAccess.newBuilder()
.allowHostFileAccess(true)
.allowHostSocketAccess(false)
.build());
}
}
// Usage
Context webContext = SecurityConfigurations.webSandbox()
.languages("js")
.build();
Context scriptContext = SecurityConfigurations.trustedScript()
.languages("js", "python")
.build();HostAccess.EXPLICIT with annotations rather than HostAccess.ALL// Web application sandbox (untrusted user scripts)
Context webSandbox = Context.newBuilder("js")
.sandbox(SandboxPolicy.UNTRUSTED)
.build();
// Microservice (trusted internal scripts)
Context microservice = Context.newBuilder("js", "python")
.sandbox(SandboxPolicy.CONSTRAINED)
.allowHostAccess(HostAccess.EXPLICIT)
.build();
// Development environment (full access)
Context development = Context.newBuilder()
.allowAllAccess(true)
.build();
// CI/CD pipeline (controlled access)
Context cicd = Context.newBuilder("js")
.sandbox(SandboxPolicy.ISOLATED)
.allowIO(IOAccess.newBuilder()
.allowHostFileAccess(true)
.allowHostSocketAccess(false)
.build())
.build();Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-polyglot--polyglot