GraalVM Polyglot API for embedding and executing Python code within Java applications.
—
Security and access control provide comprehensive protection mechanisms for Python code execution within Java applications. The framework offers multiple layers of security including host access policies, inter-language restrictions, I/O controls, and sandbox environments with varying trust levels.
Control how Python code can access Java objects and methods.
/**
* Host access policy that requires explicit @Export annotations
*/
public static final HostAccess EXPLICIT;
/**
* Host access policy allowing unrestricted access to all host objects
*/
public static final HostAccess ALL;
/**
* Host access policy denying all host access
*/
public static final HostAccess NONE;
/**
* Host access policy for constrained sandbox environments
*/
public static final HostAccess CONSTRAINED;
/**
* Host access policy for isolated sandbox environments
*/
public static final HostAccess ISOLATED;
/**
* Host access policy for untrusted sandbox environments
*/
public static final HostAccess UNTRUSTED;
/**
* Creates a builder for custom host access policies
* @return HostAccess.Builder for configuration
*/
public static Builder newBuilder();
/**
* Creates a builder based on an existing policy
* @param prototype existing HostAccess to use as template
* @return HostAccess.Builder for configuration
*/
public static Builder newBuilder(HostAccess prototype);Usage Examples:
// Explicit access - requires @Export annotation
public class Calculator {
@HostAccess.Export
public int add(int a, int b) {
return a + b;
}
// Not accessible from Python without @Export
public int subtract(int a, int b) {
return a - b;
}
}
Context explicitContext = Context.newBuilder("python")
.allowHostAccess(HostAccess.EXPLICIT)
.build();
Calculator calc = new Calculator();
explicitContext.getPolyglotBindings().putMember("calculator", calc);
// Only add() is accessible
Value result1 = explicitContext.eval("python", "calculator.add(5, 3)"); // Works: 8
// Value result2 = explicitContext.eval("python", "calculator.subtract(5, 3)"); // Fails
// Unrestricted access
Context allAccessContext = Context.newBuilder("python")
.allowHostAccess(HostAccess.ALL)
.build();
allAccessContext.getPolyglotBindings().putMember("calculator", calc);
Value result3 = allAccessContext.eval("python", "calculator.subtract(10, 4)"); // Works: 6
// No host access
Context noAccessContext = Context.newBuilder("python")
.allowHostAccess(HostAccess.NONE)
.build();
// Cannot pass host objects or access Java functionality
// noAccessContext.getPolyglotBindings().putMember("calculator", calc); // Would fail
// Sandbox-specific policies
Context constrainedContext = Context.newBuilder("python")
.allowHostAccess(HostAccess.CONSTRAINED)
.sandbox(SandboxPolicy.CONSTRAINED)
.build();Create fine-grained host access controls with custom rules.
/**
* Builder for creating custom host access policies
*/
public static final class HostAccess.Builder {
/**
* Allows access to all public members of specified classes
* @param classes the classes to allow access to
* @return this builder
*/
public Builder allowAccessToAllClasses(Class<?>... classes);
/**
* Allows access to members annotated with @Export
* @param export true to allow exported members
* @return this builder
*/
public Builder allowAccessAnnotatedBy(Class<? extends Annotation> annotation);
/**
* Allows access to all public members
* @param allPublic true to allow all public access
* @return this builder
*/
public Builder allowAllPublicAccess(boolean allPublic);
/**
* Allows access to array elements
* @param arrayAccess true to allow array access
* @return this builder
*/
public Builder allowArrayAccess(boolean arrayAccess);
/**
* Allows access to List elements
* @param listAccess true to allow List access
* @return this builder
*/
public Builder allowListAccess(boolean listAccess);
/**
* Allows access to Map elements
* @param mapAccess true to allow Map access
* @return this builder
*/
public Builder allowMapAccess(boolean mapAccess);
/**
* Allows buffer access for binary data
* @param bufferAccess true to allow buffer access
* @return this builder
*/
public Builder allowBufferAccess(boolean bufferAccess);
/**
* Allows implementation of functional interfaces
* @param functionalInterface true to allow functional interfaces
* @return this builder
*/
public Builder allowImplementationsAnnotatedBy(Class<? extends Annotation> annotation);
/**
* Builds the configured host access policy
* @return new HostAccess instance
*/
public HostAccess build();
}
/**
* Annotation to mark methods/fields as accessible from guest languages
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public @interface Export {
}Usage Examples:
// Custom policy allowing specific classes
HostAccess customPolicy = HostAccess.newBuilder()
.allowAccessToAllClasses(String.class, Integer.class, Double.class)
.allowArrayAccess(true)
.allowListAccess(true)
.allowMapAccess(true)
.build();
Context customContext = Context.newBuilder("python")
.allowHostAccess(customPolicy)
.build();
// Data transfer objects with selective access
public class UserData {
@HostAccess.Export
public String name;
@HostAccess.Export
public int age;
// Private - not accessible
private String socialSecurityNumber;
@HostAccess.Export
public String getDisplayName() {
return "User: " + name;
}
// Not exported - not accessible
public String getSSN() {
return socialSecurityNumber;
}
}
// Selective access policy
HostAccess selectivePolicy = HostAccess.newBuilder()
.allowAccessAnnotatedBy(HostAccess.Export.class)
.allowListAccess(true)
.build();
Context selectiveContext = Context.newBuilder("python")
.allowHostAccess(selectivePolicy)
.build();
UserData user = new UserData();
user.name = "Alice";
user.age = 30;
selectiveContext.getPolyglotBindings().putMember("user", user);
// Accessible
Value userName = selectiveContext.eval("python", "user.name"); // "Alice"
Value displayName = selectiveContext.eval("python", "user.getDisplayName()"); // "User: Alice"
// Not accessible - would throw exception
// Value ssn = selectiveContext.eval("python", "user.getSSN()");Control inter-language evaluation and data sharing between different guest languages.
/**
* Policy denying all inter-language access
*/
public static final PolyglotAccess NONE;
/**
* Policy allowing full inter-language access
*/
public static final PolyglotAccess ALL;
/**
* Creates a builder for custom polyglot access policies
* @return PolyglotAccess.Builder for configuration
*/
public static Builder newBuilder();
/**
* Builder for creating custom polyglot access policies
*/
public static final class PolyglotAccess.Builder {
/**
* Allows the specified language to evaluate code in target languages
* @param language the source language
* @param targetLanguages the languages it can evaluate
* @return this builder
*/
public Builder allowEval(String language, String... targetLanguages);
/**
* Allows binding sharing between specified languages
* @param language the source language
* @param targetLanguages the languages it can share bindings with
* @return this builder
*/
public Builder allowBindingsAccess(String language, String... targetLanguages);
/**
* Builds the configured polyglot access policy
* @return new PolyglotAccess instance
*/
public PolyglotAccess build();
}Usage Examples:
// No inter-language access
Context isolatedContext = Context.newBuilder("python", "js")
.allowPolyglotAccess(PolyglotAccess.NONE)
.build();
// Python cannot evaluate JavaScript
// isolatedContext.eval("python", "polyglot.eval('js', '1 + 1')"); // Would fail
// Full inter-language access
Context polyglotContext = Context.newBuilder("python", "js")
.allowPolyglotAccess(PolyglotAccess.ALL)
.build();
// Python can evaluate JavaScript
Value jsResult = polyglotContext.eval("python", "polyglot.eval('js', '1 + 1')"); // 2
// Custom selective access
PolyglotAccess customPolyglotAccess = PolyglotAccess.newBuilder()
.allowEval("python", "js") // Python can eval JS
.allowBindingsAccess("python", "js") // Python can access JS bindings
.build();
Context selectivePolyglotContext = Context.newBuilder("python", "js")
.allowPolyglotAccess(customPolyglotAccess)
.build();
// Share data between languages
selectivePolyglotContext.eval("js", "globalThis.shared_value = 42;");
Value sharedValue = selectivePolyglotContext.eval("python",
"polyglot.eval('js', 'globalThis.shared_value')"); // 42Define security levels with predefined sandbox configurations.
/**
* Sandbox policy enumeration defining security levels
*/
public enum SandboxPolicy {
/**
* Fully trusted applications with no restrictions (default)
*/
TRUSTED,
/**
* Trusted but potentially buggy applications with basic protections
*/
CONSTRAINED,
/**
* Applications with potential security vulnerabilities requiring isolation
*/
ISOLATED,
/**
* Fully untrusted applications requiring maximum security
*/
UNTRUSTED
}Usage Examples:
// Trusted environment - no restrictions
Context trustedContext = Context.newBuilder("python")
.sandbox(SandboxPolicy.TRUSTED)
.allowHostAccess(HostAccess.ALL)
.allowIO(IOAccess.ALL)
.build();
// Full access to system resources
trustedContext.eval("python", """
import os
import subprocess
print(os.getcwd())
# Can access file system, network, etc.
""");
// Constrained environment - limited but functional
Context constrainedContext = Context.newBuilder("python")
.sandbox(SandboxPolicy.CONSTRAINED)
.allowHostAccess(HostAccess.CONSTRAINED)
.allowIO(IOAccess.newBuilder()
.allowHostFileAccess(Path.of("/app/data"))
.build())
.build();
// Limited file access, controlled host access
constrainedContext.eval("python", """
# Can read from /app/data directory
with open('/app/data/config.txt', 'r') as f:
config = f.read()
print(config)
""");
// Isolated environment - strong restrictions
Context isolatedContext = Context.newBuilder("python")
.sandbox(SandboxPolicy.ISOLATED)
.allowHostAccess(HostAccess.ISOLATED)
.allowIO(IOAccess.NONE)
.build();
// Very limited access
isolatedContext.eval("python", """
# Pure computation only
result = sum(range(100))
print(f"Sum: {result}")
# Cannot access files, network, or most host functionality
""");
// Untrusted environment - maximum security
Context untrustedContext = Context.newBuilder("python")
.sandbox(SandboxPolicy.UNTRUSTED)
.allowHostAccess(HostAccess.UNTRUSTED)
.allowIO(IOAccess.NONE)
.allowPolyglotAccess(PolyglotAccess.NONE)
.resourceLimits(ResourceLimits.newBuilder()
.statementLimit(10000, null)
.timeLimit(Duration.ofSeconds(5))
.build())
.build();
// Maximum restrictions with resource limits
untrustedContext.eval("python", """
# Only basic computation allowed
x = 42
y = x * 2
print(y) # 84
""");Control file system, network, and other I/O operations.
/**
* I/O access policy denying all I/O operations
*/
public static final IOAccess NONE;
/**
* I/O access policy allowing full host I/O access
*/
public static final IOAccess ALL;
/**
* Creates a builder for custom I/O access policies
* @return IOAccess.Builder for configuration
*/
public static Builder newBuilder();
/**
* Creates a builder based on an existing I/O policy
* @param prototype existing IOAccess to use as template
* @return IOAccess.Builder for configuration
*/
public static Builder newBuilder(IOAccess prototype);
/**
* Builder for creating custom I/O access policies
*/
public static final class IOAccess.Builder {
/**
* Allows host file access to specified paths
* @param path the file path to allow access to
* @return this builder
*/
public Builder allowHostFileAccess(Path path);
/**
* Allows host socket access for network operations
* @param hostSocketAccess true to allow socket access
* @return this builder
*/
public Builder allowHostSocketAccess(boolean hostSocketAccess);
/**
* Sets a custom file system implementation
* @param fileSystem the FileSystem to use
* @return this builder
*/
public Builder fileSystem(FileSystem fileSystem);
/**
* Builds the configured I/O access policy
* @return new IOAccess instance
*/
public IOAccess build();
}Usage Examples:
// No I/O access
Context noIOContext = Context.newBuilder("python")
.allowIO(IOAccess.NONE)
.build();
// Cannot access files or network
// noIOContext.eval("python", "open('file.txt', 'r')"); // Would fail
// Full I/O access
Context fullIOContext = Context.newBuilder("python")
.allowIO(IOAccess.ALL)
.build();
// Can access any file or network resource
fullIOContext.eval("python", """
import urllib.request
with open('/tmp/test.txt', 'w') as f:
f.write('Hello, World!')
""");
// Custom I/O policy with restricted file access
IOAccess restrictedIO = IOAccess.newBuilder()
.allowHostFileAccess(Path.of("/app/data"))
.allowHostFileAccess(Path.of("/tmp"))
.allowHostSocketAccess(false) // No network access
.build();
Context restrictedContext = Context.newBuilder("python")
.allowIO(restrictedIO)
.build();
// Can only access specific directories
restrictedContext.eval("python", """
# Allowed
with open('/app/data/input.txt', 'r') as f:
data = f.read()
with open('/tmp/output.txt', 'w') as f:
f.write(data.upper())
# Not allowed - would fail
# with open('/etc/passwd', 'r') as f:
# content = f.read()
""");
// Virtual file system
FileSystem virtualFS = createVirtualFileSystem(); // Custom implementation
IOAccess virtualIO = IOAccess.newBuilder()
.fileSystem(virtualFS)
.build();
Context virtualContext = Context.newBuilder("python")
.allowIO(virtualIO)
.build();
// All file operations go through virtual file system
virtualContext.eval("python", """
# Uses virtual file system
with open('virtual_file.txt', 'w') as f:
f.write('This goes to virtual storage')
""");Control resource usage including CPU time, memory, and statement execution limits.
/**
* Builder for creating resource limit configurations
*/
public static final class ResourceLimits.Builder {
/**
* Sets a limit on the number of statements executed
* @param statementLimit maximum number of statements
* @param onLimit callback when limit is reached (optional)
* @return this builder
*/
public Builder statementLimit(long statementLimit, Consumer<ResourceLimitEvent> onLimit);
/**
* Sets a time limit for execution
* @param timeLimit maximum execution time
* @return this builder
*/
public Builder timeLimit(Duration timeLimit);
/**
* Builds the configured resource limits
* @return new ResourceLimits instance
*/
public ResourceLimits build();
}
/**
* Event fired when resource limits are reached
*/
public final class ResourceLimitEvent {
/**
* Gets the type of limit that was exceeded
* @return limit type description
*/
public String getLimitType();
/**
* Gets the current resource usage
* @return current usage value
*/
public long getCurrentUsage();
/**
* Gets the limit that was exceeded
* @return limit value
*/
public long getLimit();
}Usage Examples:
// Statement limit with callback
ResourceLimits statementLimits = ResourceLimits.newBuilder()
.statementLimit(1000, event -> {
System.out.println("Statement limit exceeded: " +
event.getCurrentUsage() + "/" + event.getLimit());
})
.build();
Context limitedContext = Context.newBuilder("python")
.resourceLimits(statementLimits)
.build();
try {
limitedContext.eval("python", """
# This will hit the statement limit
total = 0
for i in range(10000): # Too many iterations
total += i
print(total)
""");
} catch (PolyglotException e) {
if (e.isResourceExhausted()) {
System.out.println("Resource limit exceeded");
}
}
// Time limit
ResourceLimits timeLimits = ResourceLimits.newBuilder()
.timeLimit(Duration.ofSeconds(5))
.build();
Context timeContext = Context.newBuilder("python")
.resourceLimits(timeLimits)
.build();
try {
timeContext.eval("python", """
import time
# This will timeout
for i in range(1000000):
time.sleep(0.001) # Small delay adds up
""");
} catch (PolyglotException e) {
if (e.isResourceExhausted()) {
System.out.println("Time limit exceeded");
}
}
// Combined limits
ResourceLimits combinedLimits = ResourceLimits.newBuilder()
.statementLimit(5000, null)
.timeLimit(Duration.ofSeconds(10))
.build();
Context combinedContext = Context.newBuilder("python")
.resourceLimits(combinedLimits)
.sandbox(SandboxPolicy.CONSTRAINED)
.build();
// Reset limits if needed
combinedContext.resetLimits();/**
* Exception thrown when security policy violations occur
*/
public final class SecurityException extends PolyglotException {
/**
* Gets the security policy that was violated
* @return policy description
*/
public String getViolatedPolicy();
/**
* Gets the attempted operation that was blocked
* @return operation description
*/
public String getBlockedOperation();
}
/**
* Environment access control for process environment variables
*/
public final class EnvironmentAccess {
/**
* No access to environment variables
*/
public static final EnvironmentAccess NONE;
/**
* Full access to inherit environment variables
*/
public static final EnvironmentAccess INHERIT;
/**
* Creates custom environment access with specific variables
* @param allowedVariables map of allowed environment variables
* @return EnvironmentAccess instance
*/
public static EnvironmentAccess allowedVariables(Map<String, String> allowedVariables);
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-polyglot--python