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.
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.
- Initiation: When an unknown user messages the bot, the system returns a
pairingdecision. - Challenge: The bot provides a 6-digit pairing code (often via console or a side-channel).
- Verification: Once the user provides the correct code, their unique account ID is added to the Store-backed Allowlist.
- 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.yamlor 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
httpandhttps.
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:
- DM Pairing: Implement the 6-digit pairing flow before allowing any tool interaction in DMs.
- Access Decision Logic: Port the
resolveDmGroupAccessDecisionpattern to Channels to centralize authorization. - SSRF Guards: Ensure any "web search" or "fetch" skills implemented in Skills cannot hit internal Luna metadata services.
- Docker Isolation: Before enabling
shell_execute, Luna must implement the Docker-based sandboxing seen in OpenClaw.