Files
Luna/Documentation/References/OpenClaw/Security.md
T
darman 797fc74e11 Add project documentation and reference materials
Include Luna AI Assistant design docs covering channels, configuration,
core architecture, memory, scheduler, and skills. Add reference docs
from OpenClaw and ZeroClaw projects, plus Mistral and OpenAI API specs.
2026-04-04 04:14:06 +02:00

6.1 KiB

Security

OpenClaw implements a multi-layered security model designed to isolate tool execution and strictly control access via Direct Messages (DMs) and Groups. This model ensures that only authorized users can trigger sensitive operations while protecting the host system from potentially malicious tool output or SSRF attacks.


DM/Group Access Decision System

The core logic for determining if a message should be processed resides in src/security/dm-policy-shared.ts. The system evaluates the dmPolicy and groupPolicy against the sender's identity.

Access Decision Types

The DmGroupAccessDecision type defines the three possible outcomes of an access check:

export type DmGroupAccessDecision = "allow" | "block" | "pairing";

Access Reason Codes

The system provides granular reason codes for every decision, enabling precise logging and user feedback:

export const DM_GROUP_ACCESS_REASON = {
  GROUP_POLICY_ALLOWED: "group_policy_allowed",
  GROUP_POLICY_DISABLED: "group_policy_disabled",
  GROUP_POLICY_EMPTY_ALLOWLIST: "group_policy_empty_allowlist",
  GROUP_POLICY_NOT_ALLOWLISTED: "group_policy_not_allowlisted",
  DM_POLICY_OPEN: "dm_policy_open",
  DM_POLICY_DISABLED: "dm_policy_disabled",
  DM_POLICY_ALLOWLISTED: "dm_policy_allowlisted",
  DM_POLICY_PAIRING_REQUIRED: "dm_policy_pairing_required",
  DM_POLICY_NOT_ALLOWLISTED: "dm_policy_not_allowlisted",
} as const;

Resolution Logic

The resolveDmGroupAccessDecision() function implements the policy evaluation:

export function resolveDmGroupAccessDecision(params: {
  isGroup: boolean;
  dmPolicy?: string | null;
  groupPolicy?: string | null;
  effectiveAllowFrom: Array<string | number>;
  effectiveGroupAllowFrom: Array<string | number>;
  isSenderAllowed: (allowFrom: string[]) => boolean;
}) {
  const dmPolicy = params.dmPolicy ?? "pairing";
  const groupPolicy = params.groupPolicy ?? "allowlist";

  if (params.isGroup) {
    // Group logic: evaluate against groupPolicy (open/disabled/allowlist)
    // Returns 'allow' if policy is open or user is in allowlist
    // Returns 'block' if policy is disabled or user not in allowlist
  } else {
    // DM logic: evaluate against dmPolicy
    if (dmPolicy === "disabled") return { decision: "block", ... };
    if (dmPolicy === "open") return { decision: "allow", ... };
    
    if (params.isSenderAllowed(effectiveAllowFrom)) {
      return { decision: "allow", reasonCode: "dm_policy_allowlisted" };
    }
    
    if (dmPolicy === "pairing") {
      return { decision: "pairing", reasonCode: "dm_policy_pairing_required" };
    }
    
    return { decision: "block", reasonCode: "dm_policy_not_allowlisted" };
  }
}

DM Pairing

The Pairing system allows users to prove their identity when dmPolicy is set to pairing.

  1. Initiation: When an unknown user messages the bot, the system returns a pairing decision.
  2. Challenge: The bot provides a 6-digit pairing code (often via console or a side-channel).
  3. Verification: Once the user provides the correct code, their unique account ID is added to the Store-backed Allowlist.
  4. Persistence: Subsequent messages from this account ID are automatically allowed as they now appear in the resolved allowlist.

Access Policies

Policies are configured per-channel and define the default security posture.

dmPolicy Options

  • disabled: The bot will not respond to any DMs.
  • open: Anyone can message the bot (high risk).
  • pairing: Users must undergo the 6-digit pairing flow to gain access.
  • allowlist: Only users explicitly listed in the configuration file can message the bot.

groupPolicy Options

  • open: Any user in the group can trigger the bot.
  • disabled: The bot is effectively silent in group settings.
  • allowlist: Only specific users within the group can trigger commands.

Allowlist Management

OpenClaw uses a hybrid allowlist system:

  • Config Allowlist: Static entries defined in the config.yaml or environment variables.
  • Store Allowlist: Dynamic entries stored in a local database (e.g., pairing-store.js), primarily populated by successful pairings.

The resolveEffectiveAllowFromLists() function merges these sources, ensuring that per-channel scoping is respected. Wildcards (*) can be used in the config to grant broad access, though this is discouraged for production environments.


Per-Session Sandboxing

To prevent tool execution from compromising the host, OpenClaw supports isolated backends:

  • Docker Backend: Each session spawns a transient container. Tools execute inside this container with limited CPU, memory, and no access to the host filesystem.
  • SSH Backend: Tools are executed on a remote machine or VM, isolating the main bot process from the execution environment.

Tool Allow/Deny Lists

Security is further tightened by restricting which tools are available to which users or channels.

  • Global Denylist: Prevents high-risk tools (like shell_execute) from being loaded.
  • Per-User Permissions: Can restrict specific tools to "Admin" users only.

SSRF Guards

The web_fetch tool and other network-touching skills include SSRF (Server-Side Request Forgery) protection. This includes:

  • IP Blocklists: Preventing requests to localhost, 127.0.0.1, and internal private IP ranges (10.0.0.0/8, etc.).
  • Protocol Restriction: Only allowing http and https.

Relevance to Luna

Luna currently lacks a security layer, which is a critical blocker for exposing tool execution to external interfaces.

Priority Patterns to Adopt:

  1. DM Pairing: Implement the 6-digit pairing flow before allowing any tool interaction in DMs.
  2. Access Decision Logic: Port the resolveDmGroupAccessDecision pattern to Channels to centralize authorization.
  3. SSRF Guards: Ensure any "web search" or "fetch" skills implemented in Skills cannot hit internal Luna metadata services.
  4. Docker Isolation: Before enabling shell_execute, Luna must implement the Docker-based sandboxing seen in OpenClaw.

Cross-refs: Core, Skills, Channels