Threat model

August 17, 2026 ยท View on GitHub

Scope

The protected asset is the Node.js/DSH host authority that should not become directly callable by model-written workflow JavaScript. Secondary assets are host availability, bounded child-agent cost, lifecycle integrity, and the integrity of data crossing the guest boundary.

The primary attacker controls the workflow body and its args. The attacker can use standard QuickJS JavaScript, invoke exposed hooks, construct arbitrary in-realm object graphs, schedule promises, throw values, and intentionally consume CPU, stack, heap, result bytes, or child-agent budget.

The following are trusted for this model: the DSH host, engine implementation, QuickJS/Emscripten dependency, Node.js runtime, operating system, package installation channel, Cordis, and selected subagent provider. Compromise of one of those components is outside the guest containment claim.

Boundary map

BoundaryAllowed crossingRejected crossing
Host to workerValidated metadata, script text, JSON args, numeric limits, shared stop signalCredentials, general environment, arbitrary host handles
Worker to QuickJSFrozen workflow hooks and JSON argsNode globals, V8 functions/objects, module loader, I/O APIs, timers
QuickJS to hostPhase/log strings and validated child-agent request dataFunctions, prototypes, symbols, cycles, non-JSON values
Host to QuickJSProjected child text or validated structured JSONLive child runs, Agents, Cordis context, provider errors as objects
Engine to observersDSH workflow/* data snapshotsLive run control and mutable final value aliases

Attacker actions

Recover host execution through JavaScript reflection

Attempt: use globalThis, constructors, prototypes, eval, or Function to reach process, require, or a V8 object.

Mitigation: these operations remain within QuickJS. No Node object is intentionally installed, and the native bridge is wrapped behind closed guest functions whose raw globals are deleted.

Residual risk: a memory-safety or bridge bug could cross the runtime boundary. This project has not received an independent security audit.

Smuggle capabilities through values

Attempt: return functions, getters, proxies, cycles, exotic prototypes, sparse arrays, non-finite numbers, or __proto__ keys that alter a host object.

Mitigation: the bridge transfers a recursive plain-JSON projection, bounds depth/size, and materializes keys as data properties. Non-JSON capabilities are not transferred.

Residual risk: logically malicious but valid JSON remains possible. Downstream code must still treat strings and records as untrusted data.

Run forever

Attempt: use a tight loop, unbounded recursion, self-renewing promise work, or ignore cancellation.

Mitigation: QuickJS interrupt fuel and shared cancellation checks stop guest execution; a host wall deadline and disposal grace end with worker.terminate().

Residual risk: host timer delivery depends on host availability. Interrupt ticks are not exact instruction accounting. Bugs in native/WASM execution may not stop as cleanly as guest bytecode.

Exhaust memory or stack

Attempt: allocate large graphs/strings, recurse deeply, or amplify serialized results.

Mitigation: QuickJS heap/stack limits, Node worker resource limits, source/result/agent-request byte caps, JSON-depth checks, and forced termination.

Residual risk: worker, WASM, message, and host bookkeeping memory is not identical to QuickJS heap accounting. Simultaneous runs multiply per-run limits.

Cause uncontrolled child fan-out or spend

Attempt: loop over agent(), create large parallel()/pipeline() arrays, or drop returned promises while continuing to enqueue work.

Mitigation: total-agent, concurrent-agent, and per-call item caps; host admission closes at terminal state; terminal settlement reaps detached calls, and dispose() waits for cleanup only within its configured bound.

Residual risk: every allowed child has real model/tool cost and authority. Provider policy and external budgets must cap that cost independently.

Abuse the allowed provider RPC

Attempt: craft prompts or provider/model selections that induce a child agent to disclose data, call tools, access networks, or make external changes.

Mitigation: the engine validates the request shape and routes only through registered DSH provider APIs.

Residual risk: this behavior is inside the allowed capability. The host provider, its prompt/tool policy, and its credentials remain trusted. Use provider-level sandboxing and approval controls.

Exploit lifecycle races

Attempt: cancel during worker boot, settle children after termination, send duplicate/late messages, or leave starts without ends.

Mitigation: ready/go startup, canonical abort signal, admission closure, first-terminal-wins state, idempotent cleanup, child ledger, and synthesized cancellation ends.

Residual risk: a provider that ignores cancellation can retain external work beyond the engine's local grace. Its process/service must enforce its own cancellation and quotas.

Compromise dependencies or build artifacts

Attempt: publish or inject malicious QuickJS glue, transitive packages, lockfile changes, or install scripts.

Mitigation: exact QuickJS version, frozen lockfile installation in CI, reviewable source, package-surface validation, and release artifacts built from the repository.

Residual risk: there is no formal provenance, reproducible-build, or independent artifact-attestation guarantee yet. Consumers should pin commits or verified releases.

Deployment tiers

ScenarioGuidance
Single-user local harness; model already has powerful toolsThis engine adds useful containment and resource controls. Keep ordinary provider approval policy.
Shared service with trusted users but model-written workflowsUse strict caps, separate provider credentials/scopes, monitoring, and per-service OS quotas.
Mutually hostile tenants or arbitrary public script submissionDo not rely on this package alone. Isolate tenants in separate processes/containers/VMs with OS resource and network controls.
High-value secrets or regulated workloadsRequire a dedicated security review, dependency governance, restricted providers, and an independently enforced sandbox boundary.

Review triggers

Revisit this threat model when any of the following changes:

  • a new native callback or guest global is exposed;
  • the boundary accepts a type beyond plain JSON;
  • QuickJS, Emscripten, Node, or DSH workflow versions change;
  • workers are pooled or realms are reused;
  • provider routing or script-selectable options expand;
  • shared-memory communication expands beyond the stop signal; or
  • the engine is used for public multi-tenant script execution.