CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-graalvm-polyglot--python

GraalVM Polyglot API for embedding and executing Python code within Java applications.

Pending
Overview
Eval results
Files

security-access-control.mddocs/

Security and Access Control

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.

Capabilities

Host Access Policies

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();

Custom Host Access Policies

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()");

Polyglot Access Control

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')"); // 42

Sandbox Policies

Define 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
    """);

I/O Access Control

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')
    """);

Resource Limits

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();

Types

/**
 * 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

docs

context-management.md

engine-language-management.md

index.md

java-python-interop.md

security-access-control.md

source-management.md

value-operations.md

tile.json