Skip to Content
runelay

Security

runelay holds credentials for every account you connect, so it is locked down by default.

First access

While no account exists, signing up needs a one-time setup token. The installer generates it and prints the link (/login?mode=signup&token=…). Without RUNELAY_SETUP_TOKEN in .env, the server makes one at startup and prints the link in docker compose logs. After the first account, signups close (unless ALLOW_SIGNUP=true).

Credentials

  • Connection configs, OAuth tokens and recoverable API keys are encrypted with AES-256-GCM using RUNELAY_SECRET.
  • Agents never receive credentials: requests made with an API key, and the list_connections tool, see headers and env values as ••••••.
  • Importing a client config through the API never expands ${VARS} from the server environment.
  • API keys belong to one organization. Revealing a key needs a panel session, never an API key.

Risky capabilities

VariableDefaultWhat it unlocks
RUNELAY_ENABLE_EXECUTEtrueThe execute tool. Agent code runs in QuickJS compiled to WebAssembly: a fresh sandbox per run with no filesystem, network, process or timers, 32 MB of memory and CPU and wall-clock limits. Tools cross the boundary as JSON only. Turn it off if you only want single call_tool calls.
RUNELAY_ENABLE_STDIOfalseLocal MCP servers (command). Even when on, only an owner or admin in the panel can create them, and the process gets a minimal environment (no server secrets).
RUNELAY_ALLOW_PRIVATE_URLSfalseConnections to private, loopback, link-local and CGNAT (100.64.0.0/10) addresses (SSRF protection: cloud metadata, other services on the host).

Prompt injection

Tool results come from third parties (an issue, a page, an email). runelay limits what a manipulated agent can do: it cannot read credentials, cannot pin memories (pinned memories go into every agent's instructions, so only the panel can pin) and execute code runs in a WebAssembly sandbox with no access to the server. It can still write unpinned memories and call the tools you connected, so review memory health from time to time.

Abuse and visibility

  • Every API key has a sliding-window rate limit (RUNELAY_RATE_LIMIT_PER_MINUTE, default 240). Over the limit the API answers 429 with retry-after.
  • Every request made with an API key is audited: tool calls (source, tool, result, duration) and REST calls (method, path, status, IP). Open API keys → Activity to see one key's timeline.

Network

Every outgoing request (MCP, OAuth, OpenAPI) resolves DNS and checks the address right before it goes out, and redirects are followed one hop at a time with the same check, so DNS rebinding and redirects cannot reach private addresses.

Container

The image starts as root only to fix the ownership of /data, then drops to the unprivileged node user. The application code stays read-only for that user. Keep the 127.0.0.1 binding (the default) and put HTTPS in front.

On this page