or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context-management.mdindex.mdio-filesystem.mdlanguage-execution.mdmonitoring-management.mdproxy-system.mdsecurity-access.mdvalue-interop.md

security-access.mddocs/

0

# Security and Access Control

1

2

GraalVM Polyglot API provides comprehensive security mechanisms to control access between host and guest languages. This includes host access policies, polyglot evaluation restrictions, sandboxing levels, and environment access controls.

3

4

## Host Access Policies

5

6

HostAccess controls how guest languages can interact with host (Java) objects, providing fine-grained security policies from completely open access to strict sandboxing.

7

8

### Predefined HostAccess Policies

9

10

```java { .api }

11

public final class HostAccess {

12

// Annotation-based access - only @Export members accessible

13

public static final HostAccess EXPLICIT;

14

15

// Scoped access with automatic resource cleanup

16

public static final HostAccess SCOPED;

17

18

// Full unrestricted access to all host objects

19

public static final HostAccess ALL;

20

21

// No host access allowed

22

public static final HostAccess NONE;

23

24

// Limited access suitable for constrained environments

25

public static final HostAccess CONSTRAINED;

26

27

// Method scoping enabled for enhanced isolation

28

public static final HostAccess ISOLATED;

29

30

// Strict restrictions for untrusted code execution

31

public static final HostAccess UNTRUSTED;

32

}

33

```

34

35

**Predefined Policy Examples:**

36

37

```java

38

// EXPLICIT: Only annotated members accessible

39

Context explicitContext = Context.newBuilder("js")

40

.allowHostAccess(HostAccess.EXPLICIT)

41

.build();

42

43

public class RestrictedAPI {

44

@HostAccess.Export

45

public String publicMethod() {

46

return "This is accessible";

47

}

48

49

public String privateMethod() {

50

return "This is NOT accessible";

51

}

52

}

53

54

explicitContext.getBindings("js").putMember("api", new RestrictedAPI());

55

explicitContext.eval("js", "console.log(api.publicMethod())"); // Works

56

// explicitContext.eval("js", "api.privateMethod()"); // Would throw exception

57

58

// ALL: Full access (use with caution)

59

Context openContext = Context.newBuilder("js")

60

.allowHostAccess(HostAccess.ALL)

61

.build();

62

63

// CONSTRAINED: Limited access for sandboxed execution

64

Context constrainedContext = Context.newBuilder("js")

65

.allowHostAccess(HostAccess.CONSTRAINED)

66

.sandbox(SandboxPolicy.CONSTRAINED)

67

.build();

68

```

69

70

### Custom HostAccess Configuration

71

72

```java { .api }

73

// Factory methods for custom configuration

74

public static HostAccess.Builder newBuilder();

75

public static HostAccess.Builder newBuilder(HostAccess conf);

76

```

77

78

The HostAccess.Builder provides extensive customization options:

79

80

```java { .api }

81

public static final class HostAccess.Builder {

82

// Access control methods

83

public HostAccess.Builder allowPublicAccess(boolean enabled);

84

public HostAccess.Builder allowAllImplementations(boolean enabled);

85

public HostAccess.Builder allowAllClassImplementations(boolean enabled);

86

public HostAccess.Builder allowArrayAccess(boolean enabled);

87

public HostAccess.Builder allowListAccess(boolean enabled);

88

public HostAccess.Builder allowBufferAccess(boolean enabled);

89

public HostAccess.Builder allowIterableAccess(boolean enabled);

90

public HostAccess.Builder allowIteratorAccess(boolean enabled);

91

public HostAccess.Builder allowMapAccess(boolean enabled);

92

93

// Annotation-based access

94

public HostAccess.Builder allowAccessAnnotatedBy(Class<? extends Annotation> annotation);

95

public HostAccess.Builder allowImplementationsAnnotatedBy(Class<? extends Annotation> annotation);

96

97

// Method scoping and inheritance

98

public HostAccess.Builder methodScoping(boolean enabled);

99

public HostAccess.Builder allowAccessInheritance(boolean enabled);

100

101

// Target type mappings

102

public HostAccess.Builder targetTypeMapping(Class<?> sourceType, Class<?> targetType, Predicate<Object> accepts, Function<Object, Object> converter);

103

public HostAccess.Builder targetTypeMapping(Class<?> sourceType, Class<?> targetType, Predicate<Object> accepts, Function<Object, Object> converter, HostAccess.TargetMappingPrecedence precedence);

104

105

// Build the configuration

106

public HostAccess build();

107

}

108

```

109

110

**Custom HostAccess Example:**

111

112

```java

113

// Custom access policy

114

HostAccess customAccess = HostAccess.newBuilder()

115

.allowPublicAccess(true)

116

.allowArrayAccess(true)

117

.allowListAccess(true)

118

.allowMapAccess(false) // Disable map access

119

.allowIterableAccess(true)

120

.methodScoping(true) // Enable method scoping for security

121

.allowAccessAnnotatedBy(HostAccess.Export.class)

122

.targetTypeMapping(String.class, Integer.class,

123

s -> s.matches("\\d+"),

124

s -> Integer.parseInt((String) s))

125

.build();

126

127

Context context = Context.newBuilder("js")

128

.allowHostAccess(customAccess)

129

.build();

130

131

// String to Integer conversion will work automatically

132

Value jsBindings = context.getBindings("js");

133

jsBindings.putMember("data", Arrays.asList("123", "456", "789"));

134

Value sum = context.eval("js", "data.reduce((a, b) => a + b, 0)"); // Auto-converts strings to ints

135

System.out.println(sum.asInt()); // 1368

136

```

137

138

### HostAccess Annotations

139

140

#### @HostAccess.Export

141

142

Marks fields, methods, and constructors as accessible from guest languages:

143

144

```java { .api }

145

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD})

146

@Retention(RetentionPolicy.RUNTIME)

147

public @interface Export {

148

}

149

```

150

151

#### @HostAccess.Implementable

152

153

Marks interfaces that guest languages can implement:

154

155

```java { .api }

156

@Target({ElementType.TYPE})

157

@Retention(RetentionPolicy.RUNTIME)

158

public @interface Implementable {

159

}

160

```

161

162

#### @HostAccess.DisableMethodScoping

163

164

Disables method scoping for specific elements:

165

166

```java { .api }

167

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE})

168

@Retention(RetentionPolicy.RUNTIME)

169

public @interface DisableMethodScoping {

170

}

171

```

172

173

**Annotation Examples:**

174

175

```java

176

public class SecureAPI {

177

@HostAccess.Export

178

public String version = "1.0.0";

179

180

@HostAccess.Export

181

public String getInfo() {

182

return "Secure API Information";

183

}

184

185

@HostAccess.Export

186

@HostAccess.DisableMethodScoping

187

public void unscopedMethod() {

188

// This method won't be scoped even if method scoping is enabled

189

}

190

191

// This method is not accessible from guest languages

192

public String internalMethod() {

193

return "Internal use only";

194

}

195

}

196

197

@HostAccess.Implementable

198

public interface EventListener {

199

void onEvent(String eventType, Object data);

200

}

201

202

// Usage

203

Context context = Context.newBuilder("js")

204

.allowHostAccess(HostAccess.EXPLICIT)

205

.build();

206

207

context.getBindings("js").putMember("api", new SecureAPI());

208

context.getBindings("js").putMember("EventListener", EventListener.class);

209

210

context.eval("js", """

211

console.log(api.version); // Works - exported field

212

console.log(api.getInfo()); // Works - exported method

213

214

// Implement Java interface in JavaScript

215

let listener = new EventListener({

216

onEvent: function(type, data) {

217

console.log(`Event: ${type}, Data: ${data}`);

218

}

219

});

220

""");

221

```

222

223

### Target Type Mappings

224

225

Target type mappings enable automatic conversion between types:

226

227

```java { .api }

228

public enum TargetMappingPrecedence {

229

HIGHEST, HIGH, NORMAL, LOW, LOWEST

230

}

231

232

public enum MutableTargetMapping {

233

ENABLED, DISABLED

234

}

235

```

236

237

**Type Mapping Example:**

238

239

```java

240

HostAccess customMapping = HostAccess.newBuilder()

241

.allowPublicAccess(true)

242

// Convert JavaScript objects to Java Maps

243

.targetTypeMapping(Value.class, Map.class,

244

Value::hasMembers,

245

v -> {

246

Map<String, Object> map = new HashMap<>();

247

for (String key : v.getMemberKeys()) {

248

map.put(key, v.getMember(key).as(Object.class));

249

}

250

return map;

251

})

252

// Convert Java LocalDate to JavaScript Date-like object

253

.targetTypeMapping(LocalDate.class, Value.class,

254

Objects::nonNull,

255

date -> ProxyObject.fromMap(Map.of(

256

"year", date.getYear(),

257

"month", date.getMonthValue(),

258

"day", date.getDayOfMonth()

259

)))

260

.build();

261

262

Context context = Context.newBuilder("js")

263

.allowHostAccess(customMapping)

264

.build();

265

```

266

267

## Polyglot Access Control

268

269

PolyglotAccess controls cross-language evaluation and bindings access between different guest languages.

270

271

### Predefined PolyglotAccess Policies

272

273

```java { .api }

274

public final class PolyglotAccess {

275

// Full cross-language access

276

public static final PolyglotAccess ALL;

277

278

// No cross-language access

279

public static final PolyglotAccess NONE;

280

}

281

```

282

283

### Custom PolyglotAccess Configuration

284

285

```java { .api }

286

// Factory method

287

public static PolyglotAccess.Builder newBuilder();

288

```

289

290

The PolyglotAccess.Builder provides granular control over language interactions:

291

292

```java { .api }

293

public static final class PolyglotAccess.Builder {

294

// Allow evaluation from one language to another

295

public PolyglotAccess.Builder allowEval(String from, String to);

296

297

// Allow mutual evaluation between languages

298

public PolyglotAccess.Builder allowEvalBetween(String... languages);

299

300

// Allow access to polyglot bindings

301

public PolyglotAccess.Builder allowBindingsAccess(String language);

302

303

// Deny evaluation (override previous allows)

304

public PolyglotAccess.Builder denyEval(String from, String to);

305

public PolyglotAccess.Builder denyEvalBetween(String... languages);

306

public PolyglotAccess.Builder denyBindingsAccess(String language);

307

308

// Build the configuration

309

public PolyglotAccess build();

310

}

311

```

312

313

**PolyglotAccess Examples:**

314

315

```java

316

// Allow JavaScript to evaluate Python, but not vice versa

317

PolyglotAccess restrictedPolyglot = PolyglotAccess.newBuilder()

318

.allowEval("js", "python")

319

.allowBindingsAccess("js")

320

.build();

321

322

Context context = Context.newBuilder("js", "python")

323

.allowPolyglotAccess(restrictedPolyglot)

324

.build();

325

326

// This works - JavaScript can evaluate Python

327

context.eval("js", """

328

let pythonResult = Polyglot.eval('python', '2 + 2');

329

console.log(pythonResult); // 4

330

""");

331

332

// This would fail - Python cannot evaluate JavaScript

333

// context.eval("python", "polyglot.eval(language='js', string='1 + 1')");

334

335

// Selective language interaction

336

PolyglotAccess selectiveAccess = PolyglotAccess.newBuilder()

337

.allowEvalBetween("js", "python") // Mutual JS <-> Python

338

.allowEval("ruby", "js") // Ruby -> JS only

339

.allowBindingsAccess("js") // Only JS can access bindings

340

.denyEval("python", "ruby") // Explicitly deny Python -> Ruby

341

.build();

342

```

343

344

## Sandbox Policies

345

346

SandboxPolicy defines different levels of security isolation for polyglot contexts.

347

348

### Sandbox Policy Levels

349

350

```java { .api }

351

public enum SandboxPolicy {

352

/**

353

* No restrictions - full trust (default)

354

*/

355

TRUSTED,

356

357

/**

358

* Basic restrictions for potentially unsafe operations

359

*/

360

CONSTRAINED,

361

362

/**

363

* Enhanced isolation with method scoping enabled

364

*/

365

ISOLATED,

366

367

/**

368

* Maximum restrictions for untrusted code execution

369

*/

370

UNTRUSTED;

371

372

// Comparison methods

373

public boolean isStricterThan(SandboxPolicy other);

374

public boolean isStricterOrEqual(SandboxPolicy other);

375

}

376

```

377

378

**Sandbox Policy Examples:**

379

380

```java

381

// Trusted environment (default) - no restrictions

382

Context trustedContext = Context.newBuilder("js")

383

.sandbox(SandboxPolicy.TRUSTED)

384

.allowAllAccess(true)

385

.build();

386

387

// Constrained environment - basic restrictions

388

Context constrainedContext = Context.newBuilder("js")

389

.sandbox(SandboxPolicy.CONSTRAINED)

390

.allowHostAccess(HostAccess.CONSTRAINED)

391

.allowIO(IOAccess.NONE)

392

.build();

393

394

// Isolated environment - enhanced security

395

Context isolatedContext = Context.newBuilder("js")

396

.sandbox(SandboxPolicy.ISOLATED)

397

.allowHostAccess(HostAccess.ISOLATED)

398

.allowPolyglotAccess(PolyglotAccess.NONE)

399

.allowCreateThread(false)

400

.build();

401

402

// Untrusted environment - maximum restrictions

403

Context untrustedContext = Context.newBuilder("js")

404

.sandbox(SandboxPolicy.UNTRUSTED)

405

.allowHostAccess(HostAccess.UNTRUSTED)

406

.allowPolyglotAccess(PolyglotAccess.NONE)

407

.allowIO(IOAccess.NONE)

408

.allowCreateThread(false)

409

.allowCreateProcess(false)

410

.allowNativeAccess(false)

411

.build();

412

413

// Check sandbox policy strictness

414

SandboxPolicy current = SandboxPolicy.CONSTRAINED;

415

System.out.println(current.isStricterThan(SandboxPolicy.TRUSTED)); // true

416

System.out.println(current.isStricterThan(SandboxPolicy.UNTRUSTED)); // false

417

```

418

419

## Environment Access Control

420

421

EnvironmentAccess controls access to environment variables and system properties.

422

423

### Predefined EnvironmentAccess Policies

424

425

```java { .api }

426

public final class EnvironmentAccess {

427

// Inherit environment variables from the host process

428

public static final EnvironmentAccess INHERIT;

429

430

// No access to environment variables

431

public static final EnvironmentAccess NONE;

432

}

433

```

434

435

### Custom EnvironmentAccess Configuration

436

437

```java { .api }

438

// Factory method

439

public static EnvironmentAccess.Builder newBuilder();

440

```

441

442

**EnvironmentAccess Examples:**

443

444

```java

445

// Inherit host environment

446

Context inheritContext = Context.newBuilder("js")

447

.allowEnvironmentAccess(EnvironmentAccess.INHERIT)

448

.build();

449

450

// No environment access

451

Context restrictedContext = Context.newBuilder("js")

452

.allowEnvironmentAccess(EnvironmentAccess.NONE)

453

.build();

454

455

// Custom environment configuration

456

EnvironmentAccess customEnv = EnvironmentAccess.newBuilder()

457

.allowEnvironmentAccess(Map.of(

458

"APP_NAME", "MyApplication",

459

"APP_VERSION", "1.0.0"

460

))

461

.build();

462

463

Context customContext = Context.newBuilder("js")

464

.allowEnvironmentAccess(customEnv)

465

.build();

466

```

467

468

## Complete Security Configuration Example

469

470

Here's a comprehensive example showing how to configure a secure polyglot context:

471

472

```java

473

public class SecurePolyglotSetup {

474

475

public static Context createSecureContext() {

476

// Custom host access with specific permissions

477

HostAccess secureHostAccess = HostAccess.newBuilder()

478

.allowPublicAccess(false) // Disable public access

479

.allowAccessAnnotatedBy(HostAccess.Export.class) // Only @Export members

480

.allowArrayAccess(true) // Allow array operations

481

.allowListAccess(true) // Allow list operations

482

.allowMapAccess(false) // Disable map access

483

.methodScoping(true) // Enable method scoping

484

.allowAccessInheritance(false) // Disable inheritance access

485

.build();

486

487

// Restricted polyglot access

488

PolyglotAccess polyglotAccess = PolyglotAccess.newBuilder()

489

.allowEval("js", "python") // JS can call Python

490

.allowBindingsAccess("js") // Only JS can use bindings

491

.build();

492

493

// Custom environment with minimal exposure

494

EnvironmentAccess envAccess = EnvironmentAccess.newBuilder()

495

.allowEnvironmentAccess(Map.of(

496

"NODE_ENV", "production",

497

"LOG_LEVEL", "info"

498

))

499

.build();

500

501

// Resource limits

502

ResourceLimits limits = ResourceLimits.newBuilder()

503

.statementLimit(100000, null) // Limit statement execution

504

.onLimit(event -> {

505

System.err.println("Resource limit exceeded: " + event.getLimitType());

506

})

507

.build();

508

509

// Build secure context

510

return Context.newBuilder("js", "python")

511

.sandbox(SandboxPolicy.CONSTRAINED) // Apply sandboxing

512

.allowHostAccess(secureHostAccess) // Restricted host access

513

.allowPolyglotAccess(polyglotAccess) // Limited polyglot access

514

.allowEnvironmentAccess(envAccess) // Custom environment

515

.allowIO(IOAccess.NONE) // No I/O access

516

.allowCreateThread(false) // No thread creation

517

.allowCreateProcess(false) // No process creation

518

.allowNativeAccess(false) // No native access

519

.resourceLimits(limits) // Apply resource limits

520

.build();

521

}

522

523

public static void main(String[] args) {

524

try (Context context = createSecureContext()) {

525

// Set up secure API

526

SecureAPI api = new SecureAPI();

527

context.getBindings("js").putMember("secureAPI", api);

528

529

// Execute user code safely

530

Value result = context.eval("js", """

531

let data = [1, 2, 3, 4, 5];

532

let sum = data.reduce((a, b) => a + b, 0);

533

secureAPI.processResult(sum);

534

""");

535

536

System.out.println("Execution completed safely: " + result);

537

538

} catch (PolyglotException e) {

539

if (e.isResourceExhausted()) {

540

System.err.println("Resource limits exceeded");

541

} else if (e.isHostException()) {

542

System.err.println("Host access violation: " + e.getMessage());

543

} else {

544

System.err.println("Execution error: " + e.getMessage());

545

}

546

}

547

}

548

}

549

550

class SecureAPI {

551

@HostAccess.Export

552

public String processResult(int value) {

553

if (value < 0 || value > 1000000) {

554

throw new IllegalArgumentException("Value out of allowed range");

555

}

556

return "Processed: " + value;

557

}

558

559

// This method is not accessible due to lack of @Export

560

public void dangerousOperation() {

561

System.exit(1); // This cannot be called from guest code

562

}

563

}

564

```

565

566

## Security Best Practices

567

568

### 1. Principle of Least Privilege

569

570

```java

571

// Start with most restrictive policy and add permissions as needed

572

Context context = Context.newBuilder("js")

573

.sandbox(SandboxPolicy.UNTRUSTED) // Most restrictive

574

.allowHostAccess(HostAccess.NONE) // No host access initially

575

.allowPolyglotAccess(PolyglotAccess.NONE) // No cross-language access

576

.allowIO(IOAccess.NONE) // No I/O access

577

.build();

578

```

579

580

### 2. Input Validation and Sanitization

581

582

```java

583

public class ValidatedAPI {

584

@HostAccess.Export

585

public String processUserInput(String input) {

586

if (input == null || input.length() > 1000) {

587

throw new IllegalArgumentException("Invalid input length");

588

}

589

590

// Sanitize input

591

String sanitized = input.replaceAll("[<>\"'&]", "");

592

593

return "Processed: " + sanitized;

594

}

595

}

596

```

597

598

### 3. Resource Monitoring

599

600

```java

601

ResourceLimits limits = ResourceLimits.newBuilder()

602

.statementLimit(50000, source -> !source.isInternal())

603

.onLimit(event -> {

604

// Log security event

605

SecurityLogger.logResourceExhaustion(

606

event.getLimitType(),

607

event.getConsumed(),

608

event.getLimit()

609

);

610

611

// Take action (e.g., terminate context)

612

throw new SecurityException("Resource limit exceeded: " + event.getLimitType());

613

})

614

.build();

615

```

616

617

### 4. Execution Timeouts

618

619

```java

620

Context context = Context.create("js");

621

CompletableFuture<Value> future = CompletableFuture.supplyAsync(() -> {

622

return context.eval("js", userProvidedCode);

623

});

624

625

try {

626

Value result = future.get(5, TimeUnit.SECONDS); // 5 second timeout

627

} catch (TimeoutException e) {

628

context.close(true); // Force close context

629

throw new SecurityException("Code execution timeout");

630

}

631

```

632

633

### 5. Security Audit Logging

634

635

```java

636

public class SecurityAuditLogger {

637

638

public static void logHostAccess(String member, Object target) {

639

// Log all host access attempts

640

System.err.printf("Host access: %s on %s%n", member, target.getClass());

641

}

642

643

public static void logPolyglotEval(String fromLang, String toLang, String code) {

644

// Log cross-language evaluations

645

System.err.printf("Polyglot eval: %s -> %s: %s%n", fromLang, toLang,

646

code.length() > 50 ? code.substring(0, 50) + "..." : code);

647

}

648

}

649

```