> ## 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.

# Sandlock

> Run captured programs on this Linux host, confined by Landlock and seccomp.

`sandlock` runs captured programs on this host through
[Sandlock](https://github.com/multikernel/sandlock), which confines each
process with Landlock and seccomp: it reads only the paths you grant and
writes only the ones you allow. Linux only, in the Python SDK and Node.

## Installation

Install the `sandlock` CLI on `PATH`. The full ruleset needs Linux 6.12 or
later.

## Usage

`captures` defaults to [`@external`](https://docs.mirage.strukto.ai/home/setup/runtime/overview#captures):
every program Mirage does not have itself. Name `@python` to run the host's
`python3` under Sandlock too.

> [tab] Python
>
> ```python theme={null}
> from mirage import RAMVFS, MountMode, Workspace
> from mirage.runtime.sandlock import SandlockRuntime
>
> runtime = SandlockRuntime(
>     captures=["@python", "@external"],
>     config={"fs_readable": ["/opt/tools"], "fs_writable": ["/tmp/work"]},
> )
> ws = Workspace({"/data": RAMVFS()}, mode=MountMode.EXEC, runtimes=[runtime])
> await ws.shell("python3 -c 'print(1 + 1)'")
> ```

> [tab] TypeScript
>
> ```typescript theme={null}
> import { MountMode, RAMVFS, SandlockRuntime, Workspace } from '@struktoai/mirage-node'
>
> const runtime = new SandlockRuntime({
>   captures: ['@python', '@external'],
>   config: { fsReadable: ['/opt/tools'], fsWritable: ['/tmp/work'] },
> })
> const ws = new Workspace({ '/data': new RAMVFS() }, { mode: MountMode.EXEC, runtimes: [runtime] })
> await ws.shell("python3 -c 'print(1 + 1)'")
> ```

> [tab] YAML
>
> ```yaml theme={null}
> mode: exec
> runtimes:
>   - name: sandlock
>     captures: ["@python", "@external"]
>     config:
>       fs_readable: [/opt/tools]
>       fs_writable: [/tmp/work]
>       max_memory: 512M
> mounts:
>   /data:
>     vfs: ram
> ```

## Connecting the workspace

A Sandlock program opens host paths, not the workspace's. To give it workspace
files, expose a mount as a [FUSE folder](https://docs.mirage.strukto.ai/home/setup/fuse.md) and grant it in
`fs_writable`, or `fs_readable` for read only:

```yaml theme={null}
mounts:
  /data:
    vfs: s3
    config:
      bucket: my-bucket
    backend: fuse
    mountpoint: /data
runtimes:
  - name: sandlock
    captures: ["@python", "@external"]
    config:
      fs_writable: [/data]
```

After the folder is mounted and granted, run the shared
[workspace file check](https://docs.mirage.strukto.ai/home/setup/runtime/overview.md#verify-workspace-file-access).

* Put the folder at the mount's own path when you can, so a path typed in
  the shell names the same file in the program.
* Calls into the folder follow mount modes and policies. A folder added in
  code with a session, `add_fuse_mount(prefix, mountpoint, session_id)` or
  `addFuseMount(prefix, mountpoint, sessionId)`, also follows that
  session's permissions.

## Runtime behavior

| Capability | On this host |
| - | - |
| Command | The captured program and its words, as argv |
| Piped input | stdin |
| Environment | The session's, over the config `env`; none of the host's |
| Working directory | The shell's |
| Files it can read | `/usr`, `/lib`, `/lib64`, `/bin`, `/etc`, `/proc`, `/dev`, and `fs_readable` |
| Files it can write | `fs_writable` only |
| Memory | Capped at `max_memory`, when set |
| Workspace files | Only through a FUSE folder you grant; see [above](#connecting-the-workspace) |

## Notes

* Under a [`system_time`](https://docs.mirage.strukto.ai/home/configuration#system-time), programs see
  that time through libfaketime when it is installed, and the host's
  clock without it.

* An interpreter installed outside the system paths needs an `fs_readable`
  grant.

* Host credentials are not passed to the program.

* A workspace whose [`network`](https://docs.mirage.strukto.ai/home/configuration#network) limits
  anything, or whose policies judge connections, runs nothing here: the
  program connects from this host, around both. It answers `Permission
  denied`, exit 126.

* The runtime does not create the FUSE folder or bind it to a session.

* Program lookup uses the sandbox's `PATH`, with the CLI's system default when
  the session does not set one. Add directories such as `/usr/local/bin` to the
  session's `PATH` when required. Missing-program diagnostics come from Sandlock.

* A working directory absent from the host refuses the command with exit 126.

* A [timeout](https://docs.mirage.strukto.ai/home/core/output-limits.md#limit-a-lines-time) kills the program.


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