Skip to content

Permission System

LingXiao’s permission system controls Agent tool execution permissions, supporting four permission modes and fine-grained rules.

ModeLabelDescription
strictstrictStrictest mode, all write operations require confirmation
devstandardDevelopment mode, standard permission control
networkedapprovedNetwork mode, network tools require approval
yoloyoloMost permissive mode, auto-approve (default)

Default permission mode is yolo, configured via security.permission_mode.

Terminal window
# Environment variable (hardened mode one-way lock)
export LINGXIAO_HARDENED_MODE=true
{
"security": {
"permission_mode": "dev"
}
}
ModeSandbox BackendDescription
yoloapp-guardLightweight sandbox
Other modesbubblewrapHardened sandbox

Backend fallback is enabled by default (allowBackendFallback: true).

ToolPermissionContext is the durable policy object:

interface ToolPermissionContext {
mode: 'strict' | 'dev' | 'networked' | 'yolo';
allowedHosts: string[];
sandboxBackend: 'app-guard' | 'bubblewrap';
allowBackendFallback: boolean;
allowRules: Array<{ toolName: string; pattern?: string }>;
denyRules: Array<{ toolName: string; pattern?: string }>;
askRules: Array<{ toolName: string; pattern?: string }>;
}

Effective permissions merge in this order (later layers override earlier):

LayerFileDescription
user~/.lingxiao/permissions.user.jsonUser level
project<workspace>/.lingxiao/permissions.project.jsonProject level
local<workspace>/.lingxiao/permissions.local.jsonLocal level
sessionSQLite session_stateSession level

Three rule types control tool execution:

Auto-approve matching tool calls:

{
"allowRules": [
{ "toolName": "file_read", "pattern": "src/**" },
{ "toolName": "code_search" }
]
}

Reject matching tool calls:

{
"denyRules": [
{ "toolName": "shell", "pattern": "rm -rf *" }
]
}

Require user confirmation before execution:

{
"askRules": [
{ "toolName": "file_create", "pattern": "*.env" },
{ "toolName": "shell", "pattern": "npm publish" }
]
}

deny > ask > allow. When the same tool matches multiple rules, deny takes precedence.

allowedHosts controls which hosts network tools can access:

{
"allowedHosts": [
"registry.npmjs.org",
"api.github.com",
"127.0.0.1"
]
}

Key settings in the security group:

SettingDefaultDescription
permission_modeyoloPermission mode
auto_allow_bash_if_sandboxedtrueAuto-allow bash in sandbox
dangerous_command_guardfalseDangerous command interception
block_private_networkfalseBlock private network access
identity_judge_llm_enabledfalseLLM identity second pass
hardened_modefalseHardened mode
env_allowlist[]Subprocess env allowlist

When hardened mode is enabled:

  • Disables query token, header-only authentication
  • Rate limit cooldown 30 seconds
  • Forces token authentication
  • dangerous_command_guard and block_private_network are forced on
  • LINGXIAO_HARDENED_MODE environment variable is a one-way lock; cannot be turned off via API

When a tool call matches an ask rule or a write operation in non-yolo mode, the system initiates a permission request:

  1. Request: permission:request event broadcast to WebUI
  2. Approval: User confirms or rejects in WebUI
  3. Result: permission:resolved event returns the decision
  • Non-yolo permission requests may be auto-approved
  • yolo requests still require user confirmation
  • Eternal mode replays pending non-yolo requests on enable

Permission audit records are appended to session_state under PERMISSION_AUDIT_LOG, retaining the most recent records.