Security
Millstream processes data your customers trust you with, through agents that read untrusted pages and documents. Its security model starts from that: one deployment per customer, isolated pipelines, sandboxed agents, and agent output that is validated before it goes anywhere.
Tenancy
Each customer gets a deployment of their own, on their infrastructure or a dedicated server. A deployment holds that organisation's pipelines, isolated from each other. Data never crosses deployments, and there is no shared control plane to breach.
Access
- The API and the UI listen on loopback by default.
- Exposed, they require a bearer token of at least 32 characters;
serverefuses a public address without one. - Every state-changing request is checked for a foreign
Origin, with or without the token. - TLS is terminated by your reverse proxy, or by the engine itself.
- Each webhook trigger has its own token, generated at
apply, stored as its SHA-256, rotated on demand and rate limited. - The commercial edition adds OIDC single sign-on and roles per pipeline and per inbox.
Isolation
Pipelines
- A pipeline resolves only the secrets mapped for it
- Secrets reach nodes inside deliveries, never their disks
- Limits and round-robin dispatch per pipeline
Actions
- Third-party and registry actions run as containers
- No capabilities,
no-new-privileges, read-only root - No network unless the manifest declares it
- Local executables only on nodes started with
--allow-exec
Agents
- A fresh container per item
- Only the declared tools, MCP servers and destinations
- No secrets beyond the step's config
- Per-call, per-run and per-day cost limits
Proposed code
- Untrusted until a person accepts it
- Built and run only in a sandbox with no network
- External-effect actions stubbed in backtests
- Refused outright without a container runtime
Prompt injection
Crawled pages and documents reach agents, so agent output is treated as untrusted data:
- it is validated against the output schema before it goes anywhere;
- an agent gets only the tools, MCP servers and network destinations its manifest declares;
millstream checkwarns when agent output can reach a step with external effects without a review in between.
The check is advisory. The structure is what protects you: a review step without autoApprove between an agent and
an external effect puts a person in the path.
Nodes
Remote nodes authenticate with the deployment's node token over TLS. A lease is the capability: a node fetches a package or an artifact only for a delivery it currently holds, checked against the engine's leases, so a node never reads another pipeline's data by guessing a hash. Revoking a node refuses it from then on and expires its leases at once.
Secrets
Pipelines declare secret names; the environment file maps them to sources ({ env: NAME } or { file: path }).
Values are redacted from logs, events, stored config, error messages, metric labels, transcripts and recordings, by
value as well as by name. A Postgres password in a connection string is refused, in every layer: credentials come from
libpq's own variables.
Personal data
- Retention per stream expires payloads and artifacts; the item's row and lineage remain as a tombstone that says why.
- Erasure by key removes payloads, keys, artifacts, transcripts, review renderings and quoted errors, downstream and across pipelines, before it reports, and records neither the key nor the items it was asked for.
- Evidence bundles replace personal fields with a keyed hash, carry no reviewer identity or free text, and expire.
- No payload in logs. The engine, the nodes and the SDK log ids, never values.
Supply chain
Registry actions and container images are pinned by digest in millstream.lock, and runs refuse a mismatch.
Containers run by digest and are never pulled at run time. Release checksums carry a keyless cosign signature and the
image is signed by digest, with an SBOM per archive.
Reporting a vulnerability
Write to contact@monolithiclab.fr with the details and a way to reproduce. You get an acknowledgement and a fix timeline.