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

# Security

export const Dropdown = ({title, defaultOpen = false, children}) => {
  const [isOpen, setIsOpen] = React.useState(defaultOpen);
  function cn(...inputs) {
    return inputs.filter(Boolean).join(' ');
  }
  return <div>
            <button className="w-full flex justify-between items-center py-3 bg-transparent 
                border-none cursor-pointer text-left" onClick={() => setIsOpen(!isOpen)} aria-expanded={isOpen}>
                <span className="font-bold text-gray-100 text-md">
                    {title}
                </span>
                <svg className={cn("transition-transform duration-200 opacity-50 flex-shrink-0", isOpen && 'rotate-90')} width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <polyline points="6 4 10 8 6 12"></polyline>
                </svg>
            </button>

            {isOpen && <div className="pb-3 space-y-4">
                    {React.Children.map(children, (child, i) => <div key={i}>{child}</div>)}
                </div>}
        </div>;
};

The Miru Agent is designed to run with minimal privileges and a restricted system footprint. This page describes the agent's authentication model, authorizations, and the security measures applied at the process, file system, network, and credential layers.

## Authentication

When the agent is first installed on a device, it goes through an activation process that establishes the device's identity:

1. The agent receives a short-lived provisioning token (either from the dashboard or an API key)
2. The agent generates a 4096-bit RSA key pair on the device
3. The agent sends the public key to the Miru control plane with its provisioning token
4. The control plane verifies the provisioning token, stores the public key, and registers the device

<img src="https://assets.mirurobotics.com/docs/v04/images/agent/security/activation.light.svg" alt="Agent authentication and activation sequence" className="block dark:hidden" />

<img src="https://assets.mirurobotics.com/docs/v04/images/agent/security/activation.dark.svg" alt="Agent authentication and activation sequence" className="hidden dark:block" />

After activation, the device's identity is tied to its RSA key pair. Notably, the key pair is generated on-device and the private key never leaves the device.

In all subsequent communication with the control plane, the private key is used to generate a short-lived JWT that authenticates the agent's requests.

### Token lifecycle

After activation, the agent authenticates API requests using short-lived JSON Web Tokens (JWTs). The process for obtaining a token works as follows:

1. The agent prepares a set of claims including its device ID, a unique nonce, and a short expiration window (a few minutes)
2. The agent signs these claims with its private RSA key
3. The agent sends the signed claims to the control plane's token endpoint
4. The control plane verifies the signature against the device's registered public key
5. If valid, the control plane issues a short-lived JWT that the agent can use for subsequent API requests

<img src="https://assets.mirurobotics.com/docs/v04/images/agent/security/token-lifecycle.light.svg" alt="Agent token lifecycle sequence" className="block dark:hidden" />

<img src="https://assets.mirurobotics.com/docs/v04/images/agent/security/token-lifecycle.dark.svg" alt="Agent token lifecycle sequence" className="hidden dark:block" />

### Token refresh

Since the JWT is short-lived, the agent runs a background process that monitors token expiration and automatically refreshes tokens before they expire. Under normal operation, this is invisible—the agent always has a valid token available for API requests.

If a token refresh fails due to a transient network issue, the agent retries automatically with increasing delays between attempts. Network interruptions do not permanently break authentication—the agent resumes normal token refresh as soon as connectivity is restored.

### Credential storage

The agent's identity is bound to the RSA key pair generated on-device during [provisioning](/cfg-mgmt/provision-devices/overview). Currently, these credentials are protected at rest through file system permissions:

| File        | Permissions | Access                            |
| ----------- | ----------- | --------------------------------- |
| Private key | `0600`      | Owner (miru) read/write only      |
| Public key  | `0640`      | Owner read/write, group read-only |

All credential files are stored under `/var/lib/miru/auth/`, owned by `miru:miru`. The private key never leaves the device—it is used locally to sign token requests but is never transmitted over the network.

Sensitive values are handled in memory using a secrecy library that minimizes exposure and zeroizes data when it is no longer needed. Tokens are redacted in log output to prevent accidental credential leakage through logs.

## Authorizations

After authentication, the control plane authorizes every request in the context of the calling device identity.

Authorization is strictly device-scoped:

* A device can only read deployments assigned to that device
* A device can only download configuration instances referenced by those assigned deployments
* A device can only report status for its own deployment records

A device cannot access fleet data outside its scope:

* It cannot list or read deployments for other devices
* It cannot download configuration instances that are not part of its assigned deployments
* It cannot write status updates for another device

This prevents lateral access between devices. Even if two devices run the same agent version, each device is isolated to its own control-plane view and assigned configuration state.

## Process sandboxing

The agent runs as a [systemd](https://en.wikipedia.org/wiki/Systemd) service with extensive hardening directives that restrict what the process can access.

<Dropdown title="Dedicated user">
  The agent runs as an unprivileged `miru` system user and group. The user has no login shell (`/bin/false`) and cannot be used for interactive access.

  You can find the agent's service unit file on [GitHub](https://github.com/mirurobotics/agent/blob/main/build/debian/miru.service) in the agent repository.
</Dropdown>

<Dropdown title="No privilege escalation">
  `NoNewPrivileges` is enabled, preventing the process from gaining additional privileges through setuid binaries or other mechanisms.
</Dropdown>

<Dropdown title="Kernel isolation">
  The agent cannot load kernel modules, modify kernel tunables (`/proc/sys`, `/sys`), or alter control groups. Other processes are hidden from the agent's view of `/proc`.
</Dropdown>

<Dropdown title="Device restrictions">
  Access to `/dev` is limited to essential pseudo-devices. Physical hardware devices are inaccessible.
</Dropdown>

<Dropdown title="Network restrictions">
  The agent can only create Unix domain sockets and IPv4/IPv6 connections. All other socket types (Netlink, packet sockets, etc.) are blocked.
</Dropdown>

## Transport security

All communication between the agent and the Miru control plane is encrypted in transit:

* **HTTPS** — REST API calls use HTTPS with TLS certificate validation
* **MQTT over TLS** — the persistent MQTT connection uses TLS on port 8883 (the standard MQTT over TLS port)

## Network posture

The agent initiates all connections outbound. No inbound ports need to be opened on the device and no listening network sockets are created.

The only local interface is a Unix domain socket at `/run/miru/miru.sock`, used by applications on the same device to query the agent's [REST API](/developers/device-api/overview). This socket is not accessible over the network.

## Local API access control

The agent's local REST API is exposed through a Unix domain socket, not a TCP port. It is not possible to access the agent's local API over a network—it is only accessible from processes running on the same device as the agent.

Access is controlled through file system permissions:

* **Socket permissions** — the socket is created with mode `0660`, restricting access to the `miru` user and group
* **Socket activation** — `systemd` manages the socket lifecycle, creating it before the agent starts and removing it when the agent stops
* **Group-based access** — applications that need to query the agent are added to the `miru` group

This means only processes running as the `miru` user or in the `miru` group can communicate with the agent's local API. Other users and processes on the device cannot access it.
