Skip to content

Runtime and Security

Andrew R. edited this page Jul 24, 2026 · 1 revision

Runtime and Security

ShamooRuntime discovers installation directories, validates immutable candidates, and runs each admitted plugin generation in a dedicated Javet Node isolate on its own daemon platform thread. All V8 creation, evaluation, event-loop pumping, callback work, resource release, and native close remain on that owner thread.

Installation lifecycle

The watched root contains direct child installation directories. Every candidate must contain shamoo-plugin.json; deploy also places compiler metadata, one platform bundle, and its source map there. Discovery rejects symlinks, path escapes, special files, malformed descriptors, unstable inventories, and duplicate plugin identities.

Runtime reads metadata and SHA-256 file inventories twice across the configured stability interval. It stages a validated copy instead of loading the mutable source directory. Startup is load, enable, ready; shutdown is drain, disable, unload. Changes prepare a separate candidate generation while the old generation remains ready, then stop old admission, drain active work, atomically publish the replacement, and clean old resources. Failed candidates do not replace the active generation.

Listeners, commands, tasks, timers, files, watchers, services, messages, proxies, and pending invocations are generation-owned. Cleanup runs in reverse order and continues after failures; leaks remain visible for retry and introspection.

JavaScript boundary

  • ESM imports resolve only registered plugin:/ modules or mediated safe builtins.
  • CommonJS uses the same restricted resolver. Absolute paths, traversal, URLs, arbitrary packages, and unregistered files are denied.
  • process, global require, module, and exports are removed before plugin execution.
  • The frozen host global has a null prototype and only explicitly registered direct callbacks.
  • Values crossing the JavaScript/Java boundary are limited to scalars, byte arrays, and acyclic string-keyed lists/maps.
  • Java objects, classes, class loaders, reflection members, dynamic proxies, Javet values, arbitrary services, and cyclic graphs are rejected.
  • Java CompletionStage results become Promises through the isolate completion queue; foreign threads do not touch V8.
  • A bounded submission queue provides backpressure. Invocations have V8 guards and configured timeouts.
  • Exact-position standard v3 source maps remap bundle errors to original TypeScript locations.

Capability matrix

Manifest capabilities are requests, not grants. Build-time compiler checks are not a sandbox, and requesting an unsupported capability does not make it available.

Capability Current Runtime behavior
Safe builtins node:assert, node:buffer, node:path, node:querystring, node:string_decoder, node:url, and node:util are available only when allow-listed
Buffer Exposed only when node:buffer is allow-listed
Filesystem Native node:fs is denied. Mediated readTextFile() and writeTextFile() enforce plugin-relative allowlists and no-follow descriptor traversal; operations fail closed without SecureDirectoryStream
Network Native modules, fetch, WebSocket, and EventSource are denied even when requested
Workers/clusters Denied even when requested
Child processes Denied even when requested
Native addons/packages Denied even when requested
NMS Compiler-gated Paper-only exact-version declarations; host implementation and compatibility are still required
Packets Requires compiler permission plus Runtime enablement and operator allowlist; see Packet Decorators
Cross-isolate channels BroadcastChannel, MessageChannel, MessageEvent, and MessagePort are removed; use versioned Shamoo contracts

Builtin aliases are normalized to node:*. The compiler checks direct imports, aliases, re-exports, transitive dependencies, and statically resolved dynamic imports. Dynamic paths that cannot be statically resolved fail compilation. A granted build-time builtin still exposes Node authority if the Runtime implements it, so grant the minimum.

Host compatibility

  • Paper Runtime: Java 21, Paper 1.21.8 build 55, Paper API 1.21.8-R0.1-20250906.215025-55.
  • Velocity Runtime: Java 21, Velocity 3.4.0; the process fixture is build 566.
  • Both artifacts embed Javet/Node 5.0.9 and currently distribute Linux x86-64 native support only.
  • Paper packets additionally require the exact Minecraft/Paper/Mache identity and fail startup on a mismatch when enabled.
  • Paper and Velocity JARs and bundles are not interchangeable.

Not an OS sandbox

Java, Javet, V8, Node native code, the adapter, plugin code, and the Minecraft server share one operating-system process. Native engine vulnerabilities, denial of service outside V8 guards, blocking trusted host callbacks, and JVM defects can affect the server. Pre-release builds should not be exposed to untrusted scripts. Run mutually untrusted plugins in a separately restricted process or container with filesystem, network, CPU, memory, and syscall controls.

GitHub provenance proves which workflow built an artifact; it does not prove that a plugin is safe. Verify checksums and attestations as described in Releases, inspect dependencies, and report vulnerabilities privately through the repository's GitHub Security Advisory flow.

Sources: Runtime internals, security policy, and lifecycle.

Clone this wiki locally