> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Security limits

> The limits that keep one agent's lines from using up what other agents and the host share.

A line an agent writes can loop forever, start processes without end, or grow
a variable until memory runs out. In Mirage it runs beside other agents'
sessions, in one process or one isolate, so each of these would cost them too.
Every limit below is on by default, and each stops its case the way bash and
Linux would, with the same exit status.

Three layers set them:

* **The host** (the server, or an edge app) sets ceilings. A workspace may
  set a lower value, never a higher one, and one that lifts a limit with
  `null` gets the ceiling instead.
* **The workspace** sets each limit for every session it holds.
* **A profile** overrides `processes` and `command_limits` for its
  sessions, field by field over the workspace's. It may raise a workspace's
  value as well as lower it; only a host ceiling holds it.

## What each limit stops

| Case | Limit | Default | What the line sees |
| - | - | - | - |
| A loop that never ends | `command_limits` `@line` `timeout_seconds` | 600 seconds | exit 124, `line: timed out after 600s` |
| A fork bomb, `b() { b \| b; }; b` | `processes.max` | 128 per session | exit 254, `bash: fork: Resource temporarily unavailable` |
| A variable that keeps doubling, `x=$x$x` | `max_env` | `2MB` per session | exit 2, `bash: xmalloc: cannot allocate N bytes (past max_env of N bytes, a mirage workspace setting)` |
| A file or a command's output held in memory | `max_memory` | `32MB` per workspace | exit 1, `line: memory exhausted`; a write to a RAM file fails with `Disk quota exceeded` |
| One API reply read whole | `max_body_bytes` | `64MB` | the call fails |
| Deep recursion in functions, `source`, `eval` or `bash -c` | 32 levels | fixed; `FUNCNEST` can lower it | exit 1, `bash: f: maximum function nesting level exceeded (32)` |
| Many sessions on one workspace | `max_sessions` | 16, or 4 on an edge runtime | HTTP 429 |
| Many workspaces on one server | `max_workspaces` | no cap | HTTP 503 |
| A burst of requests | `rate_limits` | `ip=1000/minute` | HTTP 429 |

`max_env` counts the bytes of a session's variables, functions, aliases and
positional parameters, one more for each array element and parameter, and a
session that would start past it, from the workspace's `env`, a profile's or a
snapshot, is refused. `processes.max` counts every pipeline stage, subshell
and background job a session has running. `timeout` stops the jobs its
command started when the time runs out, as GNU's does by signalling its
process group, unless it is given `--foreground` or `-s INT`. As in Bash, a
background job that is one program ignores `INT`, one that runs several
commands loses only the command, subshell or pipeline it is running and goes
on, and one that runs a function ends with it.

Some bounds are fixed:

* A session id, profile name or workspace id is 1 to 128 characters, with no
  control characters.
* A history read returns the newest 10,000 entries, and `/.bash_history` the
  newest 10,000 commands. A workspace that keeps its history in memory holds
  at most 8 MB of it, and drops the oldest entries first.
* A line sends at most 1000 `vfs.<call>` spans to
  [OpenTelemetry](https://docs.mirage.strukto.ai/home/infrastructure/history.md#send-it-to-opentelemetry),
  or as many as `MIRAGE_TRACE_MAX_SPANS` says.

## Set them on a workspace

```yaml theme={null}
max_memory: 32MB
max_env: 2MB
processes: {max: 64}
command_limits:
  "@line": {timeout_seconds: 120}
profiles:
  batch:
    processes: {max: 512}
    command_limits:
      "@line": {timeout_seconds: 900}
```

Here a `batch` session runs 512 processes and 15-minute lines, and every other
session 64 processes and 2-minute lines. See
[configuration](https://docs.mirage.strukto.ai/home/configuration.md), [profiles](https://docs.mirage.strukto.ai/home/profiles.md) and
[output limits](https://docs.mirage.strukto.ai/home/core/output-limits.md).

## Set the host's ceilings

A tenant controls its own workspace's config and profiles, so a host that
runs other people's agents holds them under ceilings. Each comes from the
app's option, else its environment variable, else its key in
`~/.mirage/config.toml`:

| Key | Env var | Holds |
| - | - | - |
| `max_memory` | `MIRAGE_MAX_MEMORY` | any workspace's `max_memory` |
| `max_env` | `MIRAGE_MAX_ENV` | any workspace's `max_env` |
| `max_processes` | `MIRAGE_MAX_PROCESSES` | any session's `processes.max` |
| `max_line_seconds` | `MIRAGE_MAX_LINE_SECONDS` | any line's time limit |
| `max_sessions` | `MIRAGE_MAX_SESSIONS` | the sessions each workspace holds |
| `max_workspaces` | `MIRAGE_MAX_WORKSPACES` | the workspaces the server holds |

```toml theme={null}
[daemon]
max_memory = "64MB"
max_env = "2MB"
max_processes = 64
max_line_seconds = 300
max_sessions = 8
```

The ceilings hold whatever sets the value: a create request, a profile
replaced over HTTP, or a snapshot loaded later. The
[Python](https://docs.mirage.strukto.ai/python/access/server.md) and [TypeScript](https://docs.mirage.strukto.ai/typescript/access/server.md)
servers and the [Cloudflare app](https://docs.mirage.strukto.ai/typescript/cloudflare-quickstart.md) take the
same settings as options.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.