TotalFusionFOR TOTAL.JS AND NODE.JS

Security

TotalFusion runs your code in other processes. This page says what that protects and what it does not.

What TotalFusion does and does not do#

  • A worker is not a sandbox, except a WebAssembly module. A Python, Rust or Go worker runs your code with your user's permissions, with your environment (pass env to restrict it), your file system and your network. Run only components you trust.
  • A WebAssembly module is a sandbox, with limits. It gets no files, no network, no environment and can import nothing but WASI, and that is tested. It is the sandbox of V8 and of WASI in Node.js: the host process has your permissions, so for code you do not trust at all, add a container or a user without privileges. See WebAssembly.
  • Describing a worker starts it. The doctor, fusion.describe() and fusion.register() read the contracts without calling any function, but a Rust or Go binary is started with --describe (what its main does before it registers the functions does run) and a WebAssembly module is started by its host, which runs the code that registers its functions. A Python component is only parsed. Use binaries and modules that you trust, also to describe them.
  • Nothing is downloaded, compiled or installed for you. The worker of Python uses the standard library, and the libraries are yours. A Rust or a Go worker is a binary you built or got precompiled.
  • Agents see only what you expose. An action is an MCP tool only if its function says mcp. The MCP endpoint of Total.js (CONF.$mcp = true) has no authentication unless you add one (Total.mcp.auth): turn it on only on a machine you control, and put authentication in front of it before anything else.
  • Total.js validates before your code runs. The input, query and params are checked against the contract, and permissions, user, sa and su are enforced by the framework before the function is reached. Your function does not see the user.
  • Errors do not leak. A ValueError in Python, Error::invalid in Rust or Invalid in Go is a mistake of the caller and its message reaches the client. Any other failure returns "The action failed" and the real error goes to the log (onerror), so paths, queries and secrets inside the messages of exceptions stay in your server.
  • Python function names are restricted to modules inside your components directory. That protects you from mistakes (calling os.system through a typo), not from an attacker: it is not a security boundary.
  • Calls are never repeated by themselves. A call that was running when its worker died may have done part of its work. Only a call you declare idempotent is repeated.
  • "$bin" is a reserved key of the protocol and cannot appear in your data.

Reporting a problem#

A vulnerability is reported privately, as SECURITY.md says. Any other problem: open an issue, with the output of npx totalfusion doctor --json, and do not include secrets in it.

Edit this page on GitHub