0
# Security and Access Control
1
2
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.
3
4
## Capabilities
5
6
### Host Access Policies
7
8
Control how Python code can access Java objects and methods.
9
10
```java { .api }
11
/**
12
* Host access policy that requires explicit @Export annotations
13
*/
14
public static final HostAccess EXPLICIT;
15
16
/**
17
* Host access policy allowing unrestricted access to all host objects
18
*/
19
public static final HostAccess ALL;
20
21
/**
22
* Host access policy denying all host access
23
*/
24
public static final HostAccess NONE;
25
26
/**
27
* Host access policy for constrained sandbox environments
28
*/
29
public static final HostAccess CONSTRAINED;
30
31
/**
32
* Host access policy for isolated sandbox environments
33
*/
34
public static final HostAccess ISOLATED;
35
36
/**
37
* Host access policy for untrusted sandbox environments
38
*/
39
public static final HostAccess UNTRUSTED;
40
41
/**
42
* Creates a builder for custom host access policies
43
* @return HostAccess.Builder for configuration
44
*/
45
public static Builder newBuilder();
46
47
/**
48
* Creates a builder based on an existing policy
49
* @param prototype existing HostAccess to use as template
50
* @return HostAccess.Builder for configuration
51
*/
52
public static Builder newBuilder(HostAccess prototype);
53
```
54
55
**Usage Examples:**
56
57
```java
58
// Explicit access - requires @Export annotation
59
public class Calculator {
60
@HostAccess.Export
61
public int add(int a, int b) {
62
return a + b;
63
}
64
65
// Not accessible from Python without @Export
66
public int subtract(int a, int b) {
67
return a - b;
68
}
69
}
70
71
Context explicitContext = Context.newBuilder("python")
72
.allowHostAccess(HostAccess.EXPLICIT)
73
.build();
74
75
Calculator calc = new Calculator();
76
explicitContext.getPolyglotBindings().putMember("calculator", calc);
77
78
// Only add() is accessible
79
Value result1 = explicitContext.eval("python", "calculator.add(5, 3)"); // Works: 8
80
// Value result2 = explicitContext.eval("python", "calculator.subtract(5, 3)"); // Fails
81
82
// Unrestricted access
83
Context allAccessContext = Context.newBuilder("python")
84
.allowHostAccess(HostAccess.ALL)
85
.build();
86
87
allAccessContext.getPolyglotBindings().putMember("calculator", calc);
88
Value result3 = allAccessContext.eval("python", "calculator.subtract(10, 4)"); // Works: 6
89
90
// No host access
91
Context noAccessContext = Context.newBuilder("python")
92
.allowHostAccess(HostAccess.NONE)
93
.build();
94
95
// Cannot pass host objects or access Java functionality
96
// noAccessContext.getPolyglotBindings().putMember("calculator", calc); // Would fail
97
98
// Sandbox-specific policies
99
Context constrainedContext = Context.newBuilder("python")
100
.allowHostAccess(HostAccess.CONSTRAINED)
101
.sandbox(SandboxPolicy.CONSTRAINED)
102
.build();
103
```
104
105
### Custom Host Access Policies
106
107
Create fine-grained host access controls with custom rules.
108
109
```java { .api }
110
/**
111
* Builder for creating custom host access policies
112
*/
113
public static final class HostAccess.Builder {
114
/**
115
* Allows access to all public members of specified classes
116
* @param classes the classes to allow access to
117
* @return this builder
118
*/
119
public Builder allowAccessToAllClasses(Class<?>... classes);
120
121
/**
122
* Allows access to members annotated with @Export
123
* @param export true to allow exported members
124
* @return this builder
125
*/
126
public Builder allowAccessAnnotatedBy(Class<? extends Annotation> annotation);
127
128
/**
129
* Allows access to all public members
130
* @param allPublic true to allow all public access
131
* @return this builder
132
*/
133
public Builder allowAllPublicAccess(boolean allPublic);
134
135
/**
136
* Allows access to array elements
137
* @param arrayAccess true to allow array access
138
* @return this builder
139
*/
140
public Builder allowArrayAccess(boolean arrayAccess);
141
142
/**
143
* Allows access to List elements
144
* @param listAccess true to allow List access
145
* @return this builder
146
*/
147
public Builder allowListAccess(boolean listAccess);
148
149
/**
150
* Allows access to Map elements
151
* @param mapAccess true to allow Map access
152
* @return this builder
153
*/
154
public Builder allowMapAccess(boolean mapAccess);
155
156
/**
157
* Allows buffer access for binary data
158
* @param bufferAccess true to allow buffer access
159
* @return this builder
160
*/
161
public Builder allowBufferAccess(boolean bufferAccess);
162
163
/**
164
* Allows implementation of functional interfaces
165
* @param functionalInterface true to allow functional interfaces
166
* @return this builder
167
*/
168
public Builder allowImplementationsAnnotatedBy(Class<? extends Annotation> annotation);
169
170
/**
171
* Builds the configured host access policy
172
* @return new HostAccess instance
173
*/
174
public HostAccess build();
175
}
176
177
/**
178
* Annotation to mark methods/fields as accessible from guest languages
179
*/
180
@Retention(RetentionPolicy.RUNTIME)
181
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
182
public @interface Export {
183
}
184
```
185
186
**Usage Examples:**
187
188
```java
189
// Custom policy allowing specific classes
190
HostAccess customPolicy = HostAccess.newBuilder()
191
.allowAccessToAllClasses(String.class, Integer.class, Double.class)
192
.allowArrayAccess(true)
193
.allowListAccess(true)
194
.allowMapAccess(true)
195
.build();
196
197
Context customContext = Context.newBuilder("python")
198
.allowHostAccess(customPolicy)
199
.build();
200
201
// Data transfer objects with selective access
202
public class UserData {
203
@HostAccess.Export
204
public String name;
205
206
@HostAccess.Export
207
public int age;
208
209
// Private - not accessible
210
private String socialSecurityNumber;
211
212
@HostAccess.Export
213
public String getDisplayName() {
214
return "User: " + name;
215
}
216
217
// Not exported - not accessible
218
public String getSSN() {
219
return socialSecurityNumber;
220
}
221
}
222
223
// Selective access policy
224
HostAccess selectivePolicy = HostAccess.newBuilder()
225
.allowAccessAnnotatedBy(HostAccess.Export.class)
226
.allowListAccess(true)
227
.build();
228
229
Context selectiveContext = Context.newBuilder("python")
230
.allowHostAccess(selectivePolicy)
231
.build();
232
233
UserData user = new UserData();
234
user.name = "Alice";
235
user.age = 30;
236
selectiveContext.getPolyglotBindings().putMember("user", user);
237
238
// Accessible
239
Value userName = selectiveContext.eval("python", "user.name"); // "Alice"
240
Value displayName = selectiveContext.eval("python", "user.getDisplayName()"); // "User: Alice"
241
242
// Not accessible - would throw exception
243
// Value ssn = selectiveContext.eval("python", "user.getSSN()");
244
```
245
246
### Polyglot Access Control
247
248
Control inter-language evaluation and data sharing between different guest languages.
249
250
```java { .api }
251
/**
252
* Policy denying all inter-language access
253
*/
254
public static final PolyglotAccess NONE;
255
256
/**
257
* Policy allowing full inter-language access
258
*/
259
public static final PolyglotAccess ALL;
260
261
/**
262
* Creates a builder for custom polyglot access policies
263
* @return PolyglotAccess.Builder for configuration
264
*/
265
public static Builder newBuilder();
266
267
/**
268
* Builder for creating custom polyglot access policies
269
*/
270
public static final class PolyglotAccess.Builder {
271
/**
272
* Allows the specified language to evaluate code in target languages
273
* @param language the source language
274
* @param targetLanguages the languages it can evaluate
275
* @return this builder
276
*/
277
public Builder allowEval(String language, String... targetLanguages);
278
279
/**
280
* Allows binding sharing between specified languages
281
* @param language the source language
282
* @param targetLanguages the languages it can share bindings with
283
* @return this builder
284
*/
285
public Builder allowBindingsAccess(String language, String... targetLanguages);
286
287
/**
288
* Builds the configured polyglot access policy
289
* @return new PolyglotAccess instance
290
*/
291
public PolyglotAccess build();
292
}
293
```
294
295
**Usage Examples:**
296
297
```java
298
// No inter-language access
299
Context isolatedContext = Context.newBuilder("python", "js")
300
.allowPolyglotAccess(PolyglotAccess.NONE)
301
.build();
302
303
// Python cannot evaluate JavaScript
304
// isolatedContext.eval("python", "polyglot.eval('js', '1 + 1')"); // Would fail
305
306
// Full inter-language access
307
Context polyglotContext = Context.newBuilder("python", "js")
308
.allowPolyglotAccess(PolyglotAccess.ALL)
309
.build();
310
311
// Python can evaluate JavaScript
312
Value jsResult = polyglotContext.eval("python", "polyglot.eval('js', '1 + 1')"); // 2
313
314
// Custom selective access
315
PolyglotAccess customPolyglotAccess = PolyglotAccess.newBuilder()
316
.allowEval("python", "js") // Python can eval JS
317
.allowBindingsAccess("python", "js") // Python can access JS bindings
318
.build();
319
320
Context selectivePolyglotContext = Context.newBuilder("python", "js")
321
.allowPolyglotAccess(customPolyglotAccess)
322
.build();
323
324
// Share data between languages
325
selectivePolyglotContext.eval("js", "globalThis.shared_value = 42;");
326
Value sharedValue = selectivePolyglotContext.eval("python",
327
"polyglot.eval('js', 'globalThis.shared_value')"); // 42
328
```
329
330
### Sandbox Policies
331
332
Define security levels with predefined sandbox configurations.
333
334
```java { .api }
335
/**
336
* Sandbox policy enumeration defining security levels
337
*/
338
public enum SandboxPolicy {
339
/**
340
* Fully trusted applications with no restrictions (default)
341
*/
342
TRUSTED,
343
344
/**
345
* Trusted but potentially buggy applications with basic protections
346
*/
347
CONSTRAINED,
348
349
/**
350
* Applications with potential security vulnerabilities requiring isolation
351
*/
352
ISOLATED,
353
354
/**
355
* Fully untrusted applications requiring maximum security
356
*/
357
UNTRUSTED
358
}
359
```
360
361
**Usage Examples:**
362
363
```java
364
// Trusted environment - no restrictions
365
Context trustedContext = Context.newBuilder("python")
366
.sandbox(SandboxPolicy.TRUSTED)
367
.allowHostAccess(HostAccess.ALL)
368
.allowIO(IOAccess.ALL)
369
.build();
370
371
// Full access to system resources
372
trustedContext.eval("python", """
373
import os
374
import subprocess
375
print(os.getcwd())
376
# Can access file system, network, etc.
377
""");
378
379
// Constrained environment - limited but functional
380
Context constrainedContext = Context.newBuilder("python")
381
.sandbox(SandboxPolicy.CONSTRAINED)
382
.allowHostAccess(HostAccess.CONSTRAINED)
383
.allowIO(IOAccess.newBuilder()
384
.allowHostFileAccess(Path.of("/app/data"))
385
.build())
386
.build();
387
388
// Limited file access, controlled host access
389
constrainedContext.eval("python", """
390
# Can read from /app/data directory
391
with open('/app/data/config.txt', 'r') as f:
392
config = f.read()
393
print(config)
394
""");
395
396
// Isolated environment - strong restrictions
397
Context isolatedContext = Context.newBuilder("python")
398
.sandbox(SandboxPolicy.ISOLATED)
399
.allowHostAccess(HostAccess.ISOLATED)
400
.allowIO(IOAccess.NONE)
401
.build();
402
403
// Very limited access
404
isolatedContext.eval("python", """
405
# Pure computation only
406
result = sum(range(100))
407
print(f"Sum: {result}")
408
# Cannot access files, network, or most host functionality
409
""");
410
411
// Untrusted environment - maximum security
412
Context untrustedContext = Context.newBuilder("python")
413
.sandbox(SandboxPolicy.UNTRUSTED)
414
.allowHostAccess(HostAccess.UNTRUSTED)
415
.allowIO(IOAccess.NONE)
416
.allowPolyglotAccess(PolyglotAccess.NONE)
417
.resourceLimits(ResourceLimits.newBuilder()
418
.statementLimit(10000, null)
419
.timeLimit(Duration.ofSeconds(5))
420
.build())
421
.build();
422
423
// Maximum restrictions with resource limits
424
untrustedContext.eval("python", """
425
# Only basic computation allowed
426
x = 42
427
y = x * 2
428
print(y) # 84
429
""");
430
```
431
432
### I/O Access Control
433
434
Control file system, network, and other I/O operations.
435
436
```java { .api }
437
/**
438
* I/O access policy denying all I/O operations
439
*/
440
public static final IOAccess NONE;
441
442
/**
443
* I/O access policy allowing full host I/O access
444
*/
445
public static final IOAccess ALL;
446
447
/**
448
* Creates a builder for custom I/O access policies
449
* @return IOAccess.Builder for configuration
450
*/
451
public static Builder newBuilder();
452
453
/**
454
* Creates a builder based on an existing I/O policy
455
* @param prototype existing IOAccess to use as template
456
* @return IOAccess.Builder for configuration
457
*/
458
public static Builder newBuilder(IOAccess prototype);
459
460
/**
461
* Builder for creating custom I/O access policies
462
*/
463
public static final class IOAccess.Builder {
464
/**
465
* Allows host file access to specified paths
466
* @param path the file path to allow access to
467
* @return this builder
468
*/
469
public Builder allowHostFileAccess(Path path);
470
471
/**
472
* Allows host socket access for network operations
473
* @param hostSocketAccess true to allow socket access
474
* @return this builder
475
*/
476
public Builder allowHostSocketAccess(boolean hostSocketAccess);
477
478
/**
479
* Sets a custom file system implementation
480
* @param fileSystem the FileSystem to use
481
* @return this builder
482
*/
483
public Builder fileSystem(FileSystem fileSystem);
484
485
/**
486
* Builds the configured I/O access policy
487
* @return new IOAccess instance
488
*/
489
public IOAccess build();
490
}
491
```
492
493
**Usage Examples:**
494
495
```java
496
// No I/O access
497
Context noIOContext = Context.newBuilder("python")
498
.allowIO(IOAccess.NONE)
499
.build();
500
501
// Cannot access files or network
502
// noIOContext.eval("python", "open('file.txt', 'r')"); // Would fail
503
504
// Full I/O access
505
Context fullIOContext = Context.newBuilder("python")
506
.allowIO(IOAccess.ALL)
507
.build();
508
509
// Can access any file or network resource
510
fullIOContext.eval("python", """
511
import urllib.request
512
with open('/tmp/test.txt', 'w') as f:
513
f.write('Hello, World!')
514
""");
515
516
// Custom I/O policy with restricted file access
517
IOAccess restrictedIO = IOAccess.newBuilder()
518
.allowHostFileAccess(Path.of("/app/data"))
519
.allowHostFileAccess(Path.of("/tmp"))
520
.allowHostSocketAccess(false) // No network access
521
.build();
522
523
Context restrictedContext = Context.newBuilder("python")
524
.allowIO(restrictedIO)
525
.build();
526
527
// Can only access specific directories
528
restrictedContext.eval("python", """
529
# Allowed
530
with open('/app/data/input.txt', 'r') as f:
531
data = f.read()
532
533
with open('/tmp/output.txt', 'w') as f:
534
f.write(data.upper())
535
536
# Not allowed - would fail
537
# with open('/etc/passwd', 'r') as f:
538
# content = f.read()
539
""");
540
541
// Virtual file system
542
FileSystem virtualFS = createVirtualFileSystem(); // Custom implementation
543
IOAccess virtualIO = IOAccess.newBuilder()
544
.fileSystem(virtualFS)
545
.build();
546
547
Context virtualContext = Context.newBuilder("python")
548
.allowIO(virtualIO)
549
.build();
550
551
// All file operations go through virtual file system
552
virtualContext.eval("python", """
553
# Uses virtual file system
554
with open('virtual_file.txt', 'w') as f:
555
f.write('This goes to virtual storage')
556
""");
557
```
558
559
### Resource Limits
560
561
Control resource usage including CPU time, memory, and statement execution limits.
562
563
```java { .api }
564
/**
565
* Builder for creating resource limit configurations
566
*/
567
public static final class ResourceLimits.Builder {
568
/**
569
* Sets a limit on the number of statements executed
570
* @param statementLimit maximum number of statements
571
* @param onLimit callback when limit is reached (optional)
572
* @return this builder
573
*/
574
public Builder statementLimit(long statementLimit, Consumer<ResourceLimitEvent> onLimit);
575
576
/**
577
* Sets a time limit for execution
578
* @param timeLimit maximum execution time
579
* @return this builder
580
*/
581
public Builder timeLimit(Duration timeLimit);
582
583
/**
584
* Builds the configured resource limits
585
* @return new ResourceLimits instance
586
*/
587
public ResourceLimits build();
588
}
589
590
/**
591
* Event fired when resource limits are reached
592
*/
593
public final class ResourceLimitEvent {
594
/**
595
* Gets the type of limit that was exceeded
596
* @return limit type description
597
*/
598
public String getLimitType();
599
600
/**
601
* Gets the current resource usage
602
* @return current usage value
603
*/
604
public long getCurrentUsage();
605
606
/**
607
* Gets the limit that was exceeded
608
* @return limit value
609
*/
610
public long getLimit();
611
}
612
```
613
614
**Usage Examples:**
615
616
```java
617
// Statement limit with callback
618
ResourceLimits statementLimits = ResourceLimits.newBuilder()
619
.statementLimit(1000, event -> {
620
System.out.println("Statement limit exceeded: " +
621
event.getCurrentUsage() + "/" + event.getLimit());
622
})
623
.build();
624
625
Context limitedContext = Context.newBuilder("python")
626
.resourceLimits(statementLimits)
627
.build();
628
629
try {
630
limitedContext.eval("python", """
631
# This will hit the statement limit
632
total = 0
633
for i in range(10000): # Too many iterations
634
total += i
635
print(total)
636
""");
637
} catch (PolyglotException e) {
638
if (e.isResourceExhausted()) {
639
System.out.println("Resource limit exceeded");
640
}
641
}
642
643
// Time limit
644
ResourceLimits timeLimits = ResourceLimits.newBuilder()
645
.timeLimit(Duration.ofSeconds(5))
646
.build();
647
648
Context timeContext = Context.newBuilder("python")
649
.resourceLimits(timeLimits)
650
.build();
651
652
try {
653
timeContext.eval("python", """
654
import time
655
# This will timeout
656
for i in range(1000000):
657
time.sleep(0.001) # Small delay adds up
658
""");
659
} catch (PolyglotException e) {
660
if (e.isResourceExhausted()) {
661
System.out.println("Time limit exceeded");
662
}
663
}
664
665
// Combined limits
666
ResourceLimits combinedLimits = ResourceLimits.newBuilder()
667
.statementLimit(5000, null)
668
.timeLimit(Duration.ofSeconds(10))
669
.build();
670
671
Context combinedContext = Context.newBuilder("python")
672
.resourceLimits(combinedLimits)
673
.sandbox(SandboxPolicy.CONSTRAINED)
674
.build();
675
676
// Reset limits if needed
677
combinedContext.resetLimits();
678
```
679
680
## Types
681
682
```java { .api }
683
/**
684
* Exception thrown when security policy violations occur
685
*/
686
public final class SecurityException extends PolyglotException {
687
/**
688
* Gets the security policy that was violated
689
* @return policy description
690
*/
691
public String getViolatedPolicy();
692
693
/**
694
* Gets the attempted operation that was blocked
695
* @return operation description
696
*/
697
public String getBlockedOperation();
698
}
699
700
/**
701
* Environment access control for process environment variables
702
*/
703
public final class EnvironmentAccess {
704
/**
705
* No access to environment variables
706
*/
707
public static final EnvironmentAccess NONE;
708
709
/**
710
* Full access to inherit environment variables
711
*/
712
public static final EnvironmentAccess INHERIT;
713
714
/**
715
* Creates custom environment access with specific variables
716
* @param allowedVariables map of allowed environment variables
717
* @return EnvironmentAccess instance
718
*/
719
public static EnvironmentAccess allowedVariables(Map<String, String> allowedVariables);
720
}
721
```