Skip to content
SENS Platform Docs

Flow Script Sandbox Threat Model

Custom TypeScript source is untrusted even when a Platform Admin created it. The platform does not claim that quickjs-emscripten has completed an external, comprehensive security audit. QuickJS isolation, a dedicated Pod and negative tests form defense in depth; the production gate therefore includes a security review in the target cluster.

The sandbox may transform bounded JSON input into bounded JSON output. It may not persist data, create measurement or Action intents, access another tenant, read secrets, contact a network service other than NATS request/reply, or retain state across requests.

Platform API / flow-worker
-- checksum + compiled artifact + bounded JSON --> NATS sandbox subject
-- success or classified safe failure ---------> reply inbox
script-sandbox-worker Pod
-- fresh WASM runtime + context per request ---> untrusted code

The Platform API and flow worker use requester-only NATS identities. The sandbox identity may subscribe only to sens.flow.sandbox.execute.v1 and publish only to reply inboxes. It receives no database, SMTP, tenant or platform credentials, no service-account token and no writable application volume.

ThreatPreventive and detective controls
Import or host capability accessTypeScript AST rejects static/dynamic imports and forbidden globals; no QuickJS module loader or host callbacks are registered.
Time, randomness or code generationDate, timers, randomness, eval and Function are rejected statically and removed at runtime.
CPU denial of serviceInterrupt handler enforces 100 ms execution; caller and NATS deadlines are bounded; timeout is non-retryable.
Memory or stack denial of service16 MiB runtime memory limit, bounded stack, 256 KiB input/output/artifact limits and fresh runtime lifecycle.
Cross-request stateMutable top-level state and class instances are rejected; a new runtime and context is created for every request.
Artifact substitutionRelease stores SHA-256; compiled plans pin artifact, manifest and schema checksums; API, worker and sandbox compare them.
Data exfiltrationNetworkPolicy permits only NATS egress, the Pod has no secrets, and source/input/output are excluded from logs.
Tenant schema forgeryServer allocates custom schema IDs and resolves only built-in, released platform or same-tenant released schemas. Foreign schemas appear absent.
Resource-handle leakRuntime, context, values and interrupt resources are released in success, script-error and host-error paths; repeated failure tests monitor memory.

NATS timeout and sandbox unavailability are technical and retryable. Script timeout, memory or stack exhaustion, script exceptions, invalid output, checksum mismatch and contract mismatch are non-retryable. Release returns structured 422 issues for technical validation failures. An unavailable sandbox returns 503 and leaves the draft unchanged.

  • static negative tests for imports, async functions, global state and every forbidden API;
  • runtime tests for infinite loops, memory pressure, stack exhaustion, checksum mismatch and malformed output;
  • Pod inspection proving non-root, read-only root filesystem, no service token, no secrets and RuntimeDefault seccomp;
  • NetworkPolicy test proving all egress except the NATS destination fails;
  • NATS permission tests proving requester and sandbox identities cannot access another service contract;
  • soak test demonstrating that handles and WASM memory do not accumulate;
  • recorded review of the exact quickjs-emscripten and compiler versions.

Until this evidence exists for the target cluster, SENS_FLOW_SANDBOX_REQUESTS_ENABLED and the flow workload remain disabled in production values.