메인 콘텐츠로 건너뛰기

Security

[!WARNING] 개인 비서 신뢰 모델: 이 문서는 gateway 하나당 신뢰할 수 있는 운영자 경계가 하나라는 가정을 전제로 합니다. OpenClaw는 여러 적대적 사용자가 하나의 agent/gateway를 공유하는 hostile multi-tenant 보안 경계를 제공하지 않습니다. 상호 비신뢰 사용자를 다뤄야 한다면 신뢰 경계를 분리하세요. 가능하면 gateway, 자격 증명, OS 사용자, 호스트를 각각 나누는 것이 좋습니다.

Scope first: personal assistant security model

OpenClaw 보안 가이드는 개인 비서 모델을 전제로 합니다. 신뢰 경계는 하나이고, 그 안에 여러 agent가 있을 수 있습니다.
  • 권장 보안 태세: gateway 하나당 사용자/신뢰 경계 하나
  • 지원하지 않는 경계: 서로 신뢰하지 않는 여러 사용자가 하나의 gateway나 agent를 공유하는 구성
  • 적대적 사용자 격리가 필요하면 신뢰 경계별로 gateway를 분리하고, 가능하면 OS 사용자/호스트도 분리
  • 여러 비신뢰 사용자가 하나의 도구 활성 agent에 메시지를 보낼 수 있다면, 그 agent의 위임된 도구 권한을 사실상 공유한다고 봐야 함
이 문서는 그 모델 안에서 하드닝하는 방법을 설명합니다. 하나의 공유 gateway 위에서 hostile multi-tenant isolation을 보장한다고 주장하지 않습니다.

Quick check: openclaw security audit

참고: Formal Verification (Security Models) config를 바꾸거나 network surface를 노출했다면 다음 명령을 정기적으로 실행하세요.
openclaw security audit
openclaw security audit --deep
openclaw security audit --fix
openclaw security audit --json
이 명령은 Gateway 인증 노출, browser control 노출, elevated allowlist, filesystem permission 같은 흔한 실수를 점검합니다. OpenClaw는 제품이면서 동시에 실험입니다. frontier model의 행동을 실제 메시징 표면과 실제 도구에 연결하고 있기 때문에 완벽하게 안전한 구성은 없습니다. 핵심은 다음 세 가지를 명확히 정하는 것입니다.
  • 누가 봇과 대화할 수 있는가
  • 봇이 어디에서 행동할 수 있는가
  • 봇이 무엇에 접근할 수 있는가
작동하는 최소 권한부터 시작하고, 충분히 신뢰가 쌓일 때만 조금씩 넓히세요.

Deployment assumption (important)

OpenClaw는 호스트와 config 경계가 신뢰된다고 가정합니다.
  • ~/.openclawopenclaw.json을 포함한 gateway host 상태를 수정할 수 있는 사람은 신뢰된 운영자로 취급합니다.
  • 여러 상호 비신뢰 운영자가 하나의 gateway를 공유하는 것은 권장하지 않습니다.
  • mixed-trust 팀이라면 gateway를 분리하고, 가능하면 OS 사용자/호스트도 나누세요.
  • 기술적으로 한 머신에서 여러 gateway를 띄울 수는 있지만, 권장 운영 기본값은 아닙니다.
  • 권장 기본값: 사용자당 머신/호스트(VPS) 하나, 그 사용자용 gateway 하나, 그 안에 하나 이상의 agent

Practical consequence (operator trust boundary)

하나의 gateway 안에서 인증된 operator access는 사용자별 tenant 역할이 아니라 신뢰된 control-plane 역할입니다.
  • 읽기/제어-plane 접근이 있는 운영자는 설계상 gateway session metadata와 history를 볼 수 있습니다.
  • sessionKey, session ID, label은 라우팅 선택자이지 인증 토큰이 아닙니다.
  • sessions.list, sessions.preview, chat.history 같은 메서드에서 운영자별 완전 격리를 기대하는 것은 이 모델 밖의 요구입니다.
  • hostile-user isolation이 필요하면 trust boundary별로 별도 gateway를 사용하세요.

Personal assistant model (not a multi-tenant bus)

OpenClaw는 개인 비서 모델용입니다. 신뢰 경계는 하나이고, 여러 agent가 있을 수 있습니다.
  • 여러 사람이 하나의 tool-enabled agent와 대화할 수 있다면, 모두가 같은 권한 세트를 사실상 조종할 수 있습니다.
  • 사용자별 session/memory 격리는 privacy에는 도움이 되지만, 공유 agent를 사용자별 host authorization 경계로 바꾸지는 않습니다.
  • 상호 적대적일 수 있는 사용자라면 trust boundary별로 gateway를 분리해야 합니다.

Shared Slack workspace: real risk

Slack 전체가 봇에게 메시지를 보낼 수 있다면 핵심 위험은 위임된 도구 권한입니다.
  • 허용된 발신자는 agent policy 안에서 exec, browser, network/file tool을 유도할 수 있습니다.
  • 한 사용자의 prompt/content injection이 shared state, device, output에 영향을 줄 수 있습니다.
  • 공유 agent가 민감한 credential/file에 접근 가능하다면, 허용된 발신자가 tool 사용을 통해 유출을 유도할 수 있습니다.
팀 워크플로용 agent는 별도 구성하고, 개인 데이터용 agent는 private하게 유지하세요.

Company-shared agent: acceptable pattern

같은 trust boundary 안의 팀이 업무 전용 범위로만 사용하는 agent라면 허용 가능합니다.
  • 전용 머신/VM/컨테이너에서 실행
  • 전용 OS 사용자 + 전용 browser/profile/account 사용
  • 개인 Apple/Google 계정이나 개인 password-manager/browser profile에 로그인하지 않기
개인 정체성과 회사 정체성을 같은 runtime에 섞으면 분리가 무너지고 개인 데이터 노출 위험이 커집니다.

Gateway and node trust concept

Gateway와 node는 역할은 다르지만 같은 operator trust domain으로 봐야 합니다.
  • Gateway는 control plane과 policy surface(gateway.auth, tool policy, routing)
  • Node는 paired device 위의 remote execution surface(command, device action, host-local capability)
  • gateway에 인증된 호출자는 gateway 범위에서 신뢰됩니다.
  • pairing 이후의 node action은 해당 node에서의 trusted operator action입니다.
  • sessionKey는 routing/context selector이지 per-user auth가 아닙니다.
  • exec approval은 operator intent를 확인하는 guardrail이지 hostile multi-tenant isolation 메커니즘이 아닙니다.
강한 격리가 필요하면 OS 사용자/호스트 단위로 trust boundary를 나누세요.

Trust boundary matrix

Boundary or controlWhat it meansCommon misread
gateway.authgateway API 호출자를 인증”매 프레임마다 서명이 있어야 안전하다”
sessionKeycontext/session 선택용 routing key”session key가 user auth boundary다”
Prompt/content guardrails모델 오용 위험 완화”prompt injection만으로 auth bypass가 증명된다”
canvas.eval / browser evaluate의도적으로 켠 operator capability”JS eval primitive가 있으면 무조건 취약점이다”
Local TUI ! shelloperator가 직접 트리거한 로컬 실행”로컬 shell convenience가 곧 remote injection이다”
Node pairing / node commandspaired device에서의 operator-level remote execution”기본적으로 비신뢰 사용자 접근으로 봐야 한다”

Not vulnerabilities by design

다음 패턴은 실제 경계 우회가 증명되지 않으면 보통 취약점으로 보지 않습니다.
  • policy/auth/sandbox bypass가 없는 prompt-injection-only chain
  • hostile multi-tenant 환경을 가정한 주장
  • 공유 gateway에서 정상적인 operator read path를 IDOR로 분류하는 주장
  • localhost-only 배포의 HSTS 같은 지적
  • 이 저장소에 존재하지 않는 inbound webhook path의 서명 문제
  • sessionKey를 auth token처럼 해석한 주장

Researcher preflight checklist

보안 이슈를 올리기 전에 다음을 확인하세요.
  1. 최신 main 또는 최신 릴리스에서 재현되는가
  2. 정확한 code path(file, function, line range)와 테스트한 version/commit이 있는가
  3. 영향이 문서화된 trust boundary를 실제로 넘는가
  4. Out of Scope에 이미 해당하지 않는가
  5. 기존 advisory와 중복되지 않는가
  6. deployment assumption(local/loopback vs exposed, trusted vs untrusted operator)을 명시했는가

Hardened baseline in 60 seconds

먼저 이 기본선부터 적용하고, 그다음 신뢰된 agent별로 필요한 도구만 다시 열어 주세요.
{
  gateway: {
    mode: "local",
    bind: "loopback",
    auth: { mode: "token", token: "replace-with-long-random-token" },
  },
  session: {
    dmScope: "per-channel-peer",
  },
  tools: {
    profile: "messaging",
    deny: ["group:automation", "group:runtime", "group:fs", "sessions_spawn", "sessions_send"],
    fs: { workspaceOnly: true },
    exec: { security: "deny", ask: "always" },
    elevated: { enabled: false },
  },
  channels: {
    whatsapp: { dmPolicy: "pairing", groups: { "*": { requireMention: true } } },
  },
}
이 구성은 gateway를 local-only로 유지하고, DM을 분리하며, control-plane/runtime 도구를 기본 차단합니다.

Shared inbox quick rule

여러 사용자가 봇에게 DM을 보낼 수 있다면:
  • session.dmScope"per-channel-peer"로 설정
  • dmPolicy"pairing" 또는 엄격한 allowlist로 유지
  • 이것은 협업용 inbox hardening이지 hostile host isolation이 아님을 기억

What the audit checks (high level)

openclaw security audit는 보통 다음 영역을 살핍니다.
  • gateway bind/auth 노출
  • control UI/browser 원격 제어 surface
  • elevated, runtime, filesystem tool exposure
  • sandboxing과 workspace scope
  • credential/config/state file permission
  • plugin/extension 노출
  • model/tool 조합이 너무 위험한지 여부

Credential storage map

주요 자격 증명 저장 위치:
  • WhatsApp account state: ~/.openclaw/credentials/whatsapp/<accountId>/creds.json
  • Allowlist/pairing state:
    • ~/.openclaw/credentials/<channel>-allowFrom.json
    • ~/.openclaw/credentials/<channel>-<accountId>-allowFrom.json
  • Model auth profiles: ~/.openclaw/agents/<agentId>/agent/auth-profiles.json
  • Optional file-backed secrets payload: ~/.openclaw/secrets.json
  • Legacy OAuth import: ~/.openclaw/credentials/oauth.json

Security Audit Checklist

audit 결과를 볼 때 우선순위는 보통 다음 순서입니다.
  1. open + tools enabled: DM/group 노출부터 줄이고 tool policy와 sandboxing을 조정
  2. public network exposure: LAN bind, Funnel, missing auth는 즉시 수정
  3. browser control remote exposure: operator access처럼 취급
  4. permissions: state/config/credential/auth가 group/world-readable인지 확인
  5. plugins/extensions: 신뢰하는 것만 로드
  6. model choice: tools가 있는 bot에는 최신 지시 추종성이 강한 모델 사용

Security audit glossary

실운영에서 자주 보게 되는 checkId 예시:
checkIdSeverityWhy it mattersPrimary fix key/pathAuto-fix
fs.state_dir.perms_world_writablecritical다른 사용자/프로세스가 전체 OpenClaw 상태를 수정 가능~/.openclaw permissionyes
fs.config.perms_writablecritical타인이 auth/tool policy/config를 바꿀 수 있음~/.openclaw/openclaw.json permissionyes
fs.config.perms_world_readablecriticalconfig 안의 token/setting 노출config file permissionyes
gateway.bind_no_authcriticalshared secret 없이 외부 bindgateway.bind, gateway.auth.*no
gateway.loopback_no_authcriticalreverse proxy된 loopback이 무인증으로 노출될 수 있음gateway.auth.*, proxy setupno
gateway.http.no_authwarn/criticalauth.mode="none"으로 HTTP API 노출gateway.auth.mode, gateway.http.endpoints.*no
gateway.tools_invoke_http.dangerous_allowwarn/criticalHTTP API에서 위험한 도구를 다시 허용gateway.tools.allowno
gateway.nodes.allow_commands_dangerouswarn/critical고위험 node command 허용gateway.nodes.allowCommandsno
gateway.tailscale_funnelcritical공용 인터넷 노출gateway.tailscale.modeno
gateway.control_ui.allowed_origins_requiredcriticalnon-loopback Control UI에 origin allowlist가 없음gateway.controlUi.allowedOriginsno
gateway.control_ui.host_header_origin_fallbackwarn/criticalHost header fallback으로 DNS rebinding hardening 약화gateway.controlUi.dangerouslyAllowHostHeaderOriginFallbackno
gateway.control_ui.insecure_authwarninsecure auth compatibility가 켜짐gateway.controlUi.allowInsecureAuthno
gateway.control_ui.device_auth_disabledcriticaldevice identity check 비활성화gateway.controlUi.dangerouslyDisableDeviceAuthno
gateway.real_ip_fallback_enabledwarn/criticalX-Real-IP fallback 신뢰로 source-IP spoofing 가능gateway.allowRealIpFallback, gateway.trustedProxiesno
discovery.mdns_full_modewarn/criticalmDNS full mode가 cliPath/sshPort metadata를 광고discovery.mdns.mode, gateway.bindno
config.insecure_or_dangerous_flagswarninsecure/dangerous debug flag 활성화finding detail 참고no
hooks.token_too_shortwarnhook ingress brute force가 쉬워짐hooks.tokenno
hooks.request_session_key_enabledwarn/critical외부 호출자가 sessionKey를 직접 선택 가능hooks.allowRequestSessionKeyno
hooks.request_session_key_prefixes_missingwarn/critical외부 session key 형식 제한이 없음hooks.allowedSessionKeyPrefixesno
logging.redact_offwarn민감 정보가 로그/status로 샐 수 있음logging.redactSensitiveyes
sandbox.docker_config_mode_offwarnsandbox Docker config가 있지만 비활성agents.*.sandbox.modeno
sandbox.dangerous_network_modecriticalsandbox Docker network가 host 또는 container:* 사용agents.*.sandbox.docker.networkno
tools.exec.host_sandbox_no_sandbox_defaultswarnsandbox가 꺼져 있을 때 exec host=sandbox가 host exec로 풀림tools.exec.host, agents.defaults.sandbox.modeno
tools.exec.host_sandbox_no_sandbox_agentswarnagent별 exec host=sandbox도 sandbox가 꺼지면 host exec로 풀림agents.list[].tools.exec.host, agents.list[].sandbox.modeno
tools.exec.safe_bins_interpreter_unprofiledwarninterpreter/runtime bin이 safeBins에 profile 없이 있으면 exec risk 확장tools.exec.safeBins, tools.exec.safeBinProfilesno
skills.workspace.symlink_escapewarnworkspace skills/**/SKILL.md가 workspace 밖으로 resolve됨workspace skills/** filesystem stateno
security.exposure.open_groups_with_elevatedcriticalopen group + elevated tool은 고위험 injection 경로channels.*.groupPolicy, tools.elevated.*no
security.exposure.open_groups_with_runtime_or_fscritical/warnopen group이 command/file tool에 접근 가능channels.*.groupPolicy, tools.profile/deny, tools.fs.workspaceOnly, agents.*.sandbox.modeno
security.trust_model.multi_user_heuristicwarnconfig가 personal-assistant trust model과 어긋나 보임gateway 분리 또는 sandbox/tool deny/workspace scopingno
tools.profile_minimal_overriddenwarnagent override가 global minimal profile을 우회agents.list[].tools.profileno
plugins.tools_reachable_permissive_policywarnextension tool이 permissive context에서 도달 가능tools.profile, tool allow/denyno
models.small_paramscritical/info작은 모델 + 위험한 tool surface는 injection risk를 키움model choice + sandbox/tool policyno

Control UI over HTTP

Control UI가 device identity를 생성하려면 secure context(HTTPS 또는 localhost)가 필요합니다. gateway.controlUi.allowInsecureAuth는 로컬 호환성용 토글입니다.
  • localhost에서는 non-secure HTTP로 페이지를 열었을 때도 device identity 없이 Control UI auth를 허용합니다.
  • pairing check를 우회하지는 않습니다.
  • remote(non-localhost) device identity 요구사항을 완화하지도 않습니다.
가능하면 HTTPS(Tailscale Serve)나 127.0.0.1을 사용하세요. 정말 break-glass 상황에서만 gateway.controlUi.dangerouslyDisableDeviceAuth를 쓰세요. device identity check를 완전히 끄는 것으로, 심각한 보안 저하입니다. 이 값이 켜지면 openclaw security audit가 경고합니다.

Insecure or dangerous flags summary

openclaw security audit는 알려진 insecure/dangerous debug switch가 켜져 있으면 config.insecure_or_dangerous_flags를 보고합니다. 현재 이 항목에는 다음이 모입니다.
  • gateway.controlUi.allowInsecureAuth=true
  • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true
  • gateway.controlUi.dangerouslyDisableDeviceAuth=true
  • hooks.gmail.allowUnsafeExternalContent=true
  • hooks.mappings[<index>].allowUnsafeExternalContent=true
  • tools.exec.applyPatch.workspaceOnly=false
관련 dangerous* / dangerously* key 예시:
  • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback
  • gateway.controlUi.dangerouslyDisableDeviceAuth
  • browser.ssrfPolicy.dangerouslyAllowPrivateNetwork
  • channels.discord.dangerouslyAllowNameMatching
  • channels.slack.dangerouslyAllowNameMatching
  • channels.googlechat.dangerouslyAllowNameMatching
  • channels.msteams.dangerouslyAllowNameMatching
  • channels.irc.dangerouslyAllowNameMatching
  • channels.mattermost.dangerouslyAllowNameMatching
  • agents.defaults.sandbox.docker.dangerouslyAllowReservedContainerTargets
  • agents.defaults.sandbox.docker.dangerouslyAllowExternalBindSources
  • agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin
  • 같은 key의 agent별 override들

Reverse Proxy Configuration

gateway를 reverse proxy(nginx, Caddy, Traefik 등) 뒤에 둘 때는 client IP를 올바르게 판별하도록 gateway.trustedProxies를 설정해야 합니다. proxy header가 trustedProxies에 없는 주소에서 오면, gateway는 그 연결을 local client로 취급하지 않습니다. gateway auth가 꺼져 있으면 그런 연결은 거부됩니다. 이렇게 해야 proxy를 거친 연결이 localhost에서 온 것처럼 보이면서 자동 신뢰를 얻는 우회를 막을 수 있습니다.
gateway:
  trustedProxies:
    - "127.0.0.1" # proxy가 localhost에서 실행될 때
  # Optional. Default false.
  # proxy가 X-Forwarded-For를 제공할 수 없을 때만 켜세요.
  allowRealIpFallback: false
  auth:
    mode: password
    password: ${OPENCLAW_GATEWAY_PASSWORD}
trustedProxies가 설정되면 gateway는 X-Forwarded-For를 사용해 client IP를 판별합니다. X-Real-IPgateway.allowRealIpFallback: true를 명시적으로 켜지 않는 한 무시됩니다. 좋은 reverse proxy 동작(들어온 forwarding header를 덮어씀):
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
나쁜 reverse proxy 동작(비신뢰 forwarding header를 이어붙이거나 보존):
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

HSTS and origin notes

  • OpenClaw gateway는 local/loopback 우선입니다. TLS를 reverse proxy에서 종료한다면, proxy가 노출하는 HTTPS 도메인에 HSTS를 설정하세요.
  • gateway가 직접 HTTPS를 종료한다면 gateway.http.securityHeaders.strictTransportSecurity로 HSTS header를 보낼 수 있습니다.
  • 자세한 배포 가이드는 Trusted Proxy Auth를 참고하세요.
  • non-loopback Control UI 배포에서는 기본적으로 gateway.controlUi.allowedOrigins가 필요합니다.
  • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true는 Host-header origin fallback을 켜는 것으로, 위험한 operator-selected policy로 봐야 합니다.
  • DNS rebinding과 proxy host-header 동작은 deployment hardening 문제로 다루고, trustedProxies를 좁게 유지하며 gateway를 공용 인터넷에 직접 노출하지 마세요.

Local session logs live on disk

OpenClaw는 session transcript를 ~/.openclaw/agents/<agentId>/sessions/*.jsonl에 저장합니다. 이는 session continuity와 선택적인 session memory indexing에 필요하지만, 동시에 filesystem access가 있는 프로세스/사용자는 누구나 그 로그를 읽을 수 있다는 뜻입니다. 디스크 접근 자체를 trust boundary로 보고 ~/.openclaw permission을 엄격히 잠그세요. agent 간 더 강한 격리가 필요하면 별도 OS 사용자 또는 별도 호스트에서 실행하세요.

Node execution (system.run)

macOS node가 paired 상태라면 gateway는 그 node에서 system.run을 호출할 수 있습니다. 즉, Mac에 대한 remote code execution입니다.
  • node pairing(approval + token)이 필요합니다.
  • Mac 쪽에서는 Settings → Exec approvals에서 security/ask/allowlist로 제어합니다.
  • approval mode는 정확한 request context와, 가능하면 하나의 구체적인 local script/file operand에 바인딩됩니다. interpreter/runtime command에서 정확히 하나의 직접 local file을 식별할 수 없으면, approval-backed execution은 semantic coverage를 약속하는 대신 거부됩니다.
  • 원격 실행을 원하지 않으면 security를 deny로 두고 해당 Mac의 node pairing을 제거하세요.

Dynamic skills (watcher / remote nodes)

OpenClaw는 세션 도중에도 skills list를 갱신할 수 있습니다.
  • Skills watcher: SKILL.md가 바뀌면 다음 agent turn에서 skills snapshot이 바뀔 수 있음
  • Remote nodes: macOS node가 연결되면 macOS 전용 skill이 bin probing 결과에 따라 활성 대상이 될 수 있음
skill folder는 trusted code로 취급하고, 수정 권한을 엄격히 제한하세요.

The Threat Model

AI assistant는 다음을 할 수 있습니다.
  • 임의 shell command 실행
  • 파일 읽기/쓰기
  • network service 접근
  • WhatsApp 같은 채널이 연결되어 있으면 사람에게 메시지 전송
사람들은 다음을 시도할 수 있습니다.
  • AI를 속여 나쁜 행동을 하게 만들기
  • 데이터 접근을 위한 social engineering
  • 인프라 정보를 탐색하기

Core concept: access control before intelligence

여기서의 실패는 대개 정교한 exploit가 아니라, “누군가 봇에게 시켰고, 봇이 그대로 했다”에 가깝습니다. OpenClaw의 기본 태도는 다음과 같습니다.
  • Identity first: 누가 봇과 대화할 수 있는지 결정
  • Scope next: 봇이 어디에서 행동할 수 있는지 결정
  • Model last: 모델은 조작될 수 있다고 가정하고, 조작되더라도 blast radius가 작도록 설계

Command authorization model

slash command와 directive는 authorized sender에게만 적용됩니다. 인증은 channel allowlist/pairing과 commands.useAccessGroups에서 파생됩니다. channel allowlist가 비어 있거나 "*"를 포함하면, 그 채널에서는 command가 사실상 열려 있게 됩니다. /exec는 authorized operator를 위한 session-local 편의 기능일 뿐이며, config를 쓰거나 다른 session을 바꾸지 않습니다.

Control plane tools risk

두 개의 내장 tool은 persistent control-plane 변경을 만들 수 있습니다.
  • gateway: config.apply, config.patch, update.run 호출 가능
  • cron: 원래 chat/task가 끝난 뒤에도 계속 실행되는 scheduled job 생성 가능
비신뢰 콘텐츠를 다루는 agent/surface에서는 기본적으로 이 도구들을 deny하세요.
{
  tools: {
    deny: ["gateway", "cron", "sessions_spawn", "sessions_send"],
  },
}
commands.restart=false는 restart action만 막습니다. gateway의 config/update action까지 막지는 않습니다.

Plugins/extensions

plugin은 gateway와 같은 프로세스 안에서 실행됩니다. trusted code로 취급하세요.
  • 신뢰하는 출처의 plugin만 설치
  • 가능하면 명시적 plugins.allow allowlist 사용
  • 활성화 전에 plugin config를 검토
  • plugin 변경 후 gateway 재시작
  • npm으로 plugin을 설치할 때(openclaw plugins install <npm-spec>)는 untrusted code 실행처럼 취급
    • 설치 경로: ~/.openclaw/extensions/<pluginId>/ 또는 $OPENCLAW_STATE_DIR/extensions/<pluginId>/
    • OpenClaw는 npm pack 후 해당 디렉터리에서 npm install --omit=dev를 실행
    • lifecycle script가 설치 중에 코드를 실행할 수 있음
    • 가능하면 pinned exact version을 쓰고, 활성화 전에 unpacked code를 검토
자세한 내용: Plugins

DM access model (pairing / allowlist / open / disabled)

현재 DM을 받을 수 있는 모든 channel은 inbound DM을 처리하기 전에 dmPolicy(또는 *.dm.policy)로 먼저 막습니다.
  • pairing (기본값): 모르는 발신자에게 짧은 pairing code를 보내고, 승인 전까지 메시지를 무시
  • allowlist: 모르는 발신자를 즉시 차단
  • open: 누구나 DM 가능. 반드시 channel allowlist에 "*"가 있어야 함
  • disabled: inbound DM 전체 무시
CLI 승인:
openclaw pairing list <channel>
openclaw pairing approve <channel> <code>
세부 파일 경로와 동작: Pairing

DM session isolation (multi-user mode)

기본적으로 OpenClaw는 모든 DM을 main session으로 라우팅해 device와 channel을 넘나드는 대화 연속성을 유지합니다. 하지만 여러 사람이 DM할 수 있다면 DM session을 분리하는 것이 좋습니다.
{
  session: { dmScope: "per-channel-peer" },
}
이렇게 하면 사용자 간 context leakage를 막을 수 있습니다. 다만 이것은 messaging-context boundary이지 host-admin boundary가 아닙니다. host/config를 공유하는 hostile user라면 trust boundary별로 gateway를 나누세요. 위 설정을 secure DM mode로 보면 됩니다.
  • 기본값: session.dmScope: "main" (모든 DM이 하나의 session 공유)
  • local CLI onboarding 기본값: 값이 비어 있으면 session.dmScope: "per-channel-peer"를 기록
  • secure DM mode: session.dmScope: "per-channel-peer" (채널+발신자별로 분리된 DM context)
같은 채널에서 여러 account를 쓰면 per-account-channel-peer를 고려하세요. 같은 사람이 여러 채널로 연락하면 session.identityLinks로 하나의 canonical identity로 묶을 수 있습니다.

Allowlists (DM + groups) — terminology

OpenClaw에는 “누가 나를 트리거할 수 있는가”에 대한 두 층이 있습니다.
  • DM allowlist: direct message에서 누가 말할 수 있는지
    • dmPolicy="pairing"이면 승인 결과가 ~/.openclaw/credentials/의 account-scoped pairing allowlist store에 기록되고 config allowlist와 병합됩니다.
  • Group allowlist: 어떤 group/channel/guild의 메시지를 받을지
    • 예: channels.whatsapp.groups, channels.telegram.groups, channels.discord.guilds, channels.slack.channels
    • groupPolicy="allowlist"groupAllowFrom으로 group 내부 발신자도 따로 제한 가능
    • group check는 먼저 allowlist/policy, 그다음 mention/reply activation 순서
    • bot 메시지에 대한 reply(암묵적 mention)도 groupAllowFrom 같은 sender allowlist를 우회하지 않음
    • dmPolicy="open", groupPolicy="open"은 마지막 수단으로만 사용
자세한 내용: Configuration, Groups

Prompt injection (what it is, why it matters)

Prompt injection은 공격자가 “지시를 무시해라”, “파일시스템을 덤프해라”, “링크를 열고 명령을 실행해라” 같은 메시지로 모델을 위험하게 조종하는 것입니다. 강한 system prompt가 있어도 prompt injection은 해결된 문제가 아닙니다. 실제 강제력은 tool policy, exec approval, sandboxing, channel allowlist에서 나옵니다. 실전에서 도움이 되는 조치는 다음과 같습니다.
  • inbound DM을 pairing/allowlist로 잠그기
  • group에서는 mention gating 사용
  • untrusted content를 읽는 agent에서 runtime/fs/control-plane tool을 기본 deny
  • 가능한 한 sandbox와 좁은 workspace scope 사용
  • 강한 instruction-following model 사용

Unsafe external content bypass flags

외부 콘텐츠를 더 넓게 읽도록 하는 우회 플래그는 정말 필요한 경우에만 쓰세요.
  • hooks.gmail.allowUnsafeExternalContent=true
  • hooks.mappings[<index>].allowUnsafeExternalContent=true
이 값들은 external content trust 경계를 넓히므로 audit에서 위험 플래그로 묶입니다.

Prompt injection does not require public DMs

DM이 공개되지 않아도 prompt injection은 발생할 수 있습니다.
  • group allowlist 안의 사람이 악성 콘텐츠를 보낼 수 있음
  • email, web page, attached doc, pasted transcript 모두 injection surface가 될 수 있음
  • trusted sender라도 계정 탈취나 혼동된 지시를 통해 위험 입력을 보낼 수 있음
따라서 핵심은 “누가 보냈는가”보다 “무슨 surface를 agent에게 열어 두었는가”입니다.

Model strength (security note)

tool이 있는 agent에는 instruction-following이 약한 작은 모델을 기본 선택으로 두지 않는 것이 좋습니다.
  • 작은 모델은 악성 프롬프트와 role confusion에 더 쉽게 흔들릴 수 있음
  • 위험한 tool surface가 열려 있으면 그 약점이 실질적 행동으로 이어질 수 있음
  • 강한 모델도 안전하지는 않지만, 더 나은 방어선이 됨

Reasoning & verbose output in groups

group에서는 과도한 reasoning trace나 verbose output이 민감한 context와 운영 정보를 새기 쉽습니다.
  • reply는 필요한 최소한으로 유지
  • 민감한 config/path/token은 로그와 transcript에서 redaction
  • 비신뢰 group에서는 control-plane 정보와 infra detail을 자세히 말하지 않게 설계

Configuration Hardening (examples)

0) File permissions

  • ~/.openclaw는 보통 700
  • openclaw.json, auth profile, credential file은 보통 600
  • 다른 사용자나 프로세스가 읽거나 쓸 수 없도록 유지

0.4) Network exposure (bind + port + firewall)

  • 가능하면 gateway.bind: "loopback" 유지
  • LAN, tailnet, custom bind를 쓴다면 auth를 반드시 설정
  • 공개 포트 노출보다 reverse proxy + auth + firewall 조합 선호

0.4.1) Docker port publishing + UFW (DOCKER-USER)

Docker는 호스트 firewall 규칙을 우회할 수 있으므로 DOCKER-USER 체인 정책을 확인하세요.
  • 필요하지 않은 port publish 금지
  • UFW를 쓴다면 Docker와 함께 실제로 차단되는지 확인
  • container bind와 published port를 최소화

0.4.2) mDNS/Bonjour discovery (information disclosure)

mDNS full mode는 로컬 네트워크에 metadata(cliPath, sshPort 등)를 광고할 수 있습니다.
  • 일반적으로 최소 모드 사용
  • 불필요하면 discovery 자체를 끄기
  • LAN 전체가 신뢰되지 않는다면 full mode는 피하기

0.5) Lock down the Gateway WebSocket (local auth)

loopback-only라도 WS client가 쉽게 붙지 않도록 token auth를 유지하는 것이 좋습니다.
  • local process도 인증을 요구
  • dashboard나 Control UI도 같은 auth 경계를 사용
  • “로컬이니까 auth를 끈다”는 습관을 피할 것

0.6) Tailscale Serve identity headers

Tailscale Serve를 쓴다면 identity header와 trusted proxy 설정을 올바르게 맞춰야 합니다.
  • proxy header를 어디까지 신뢰할지 명확히 설정
  • tailnet 노출과 public exposure를 혼동하지 않기
  • Serve/Funnel은 운영자 접근 경계의 일부로 다루기
browser control이 필요하면 gateway host의 개인 브라우저보다 전용 node host/전용 browser profile을 권장합니다.
  • 개인 세션/쿠키와 분리
  • 업무 전용 계정만 로그인
  • 가능한 경우 sandboxed browser와 별도 device 사용

0.7) Secrets on disk (what’s sensitive)

민감한 항목:
  • gateway token/password
  • model provider API key
  • OAuth credential material
  • auth profile
  • plugin이나 helper가 추가로 쓰는 local secret file
가능하면 SecretRef와 별도 secret store를 사용하고, disk permission을 엄격히 유지하세요.

0.8) Logs + transcripts (redaction + retention)

로그와 transcript는 유출 표면입니다.
  • logging.redactSensitive를 켜기
  • 보존 기간을 필요한 만큼만 유지
  • transcript가 disk에 남는다는 점을 운영자와 팀이 이해하도록 하기

1) DMs: pairing by default

DM 기본값은 pairing으로 두세요. open DMs는 특별한 이유가 있을 때만 사용합니다.

2) Groups: require mention everywhere

group에서는 기본적으로 mention required를 권장합니다. agent가 모든 대화를 자동으로 처리하게 두지 마세요.

3) Separate Numbers

개인용 채널 계정과 회사/공유용 채널 계정을 섞지 마세요. 가능하면 전화번호, 앱 계정, 브라우저 프로필을 분리하세요.

4) Read-Only Mode (Today, via sandbox + tools)

강한 write 차단이 필요하면:
  • filesystem tool deny
  • sandbox 활성화
  • workspaceAccess: "ro" 또는 "none"
  • runtime/control-plane tool deny

5) Secure baseline (copy/paste)

{
  session: { dmScope: "per-channel-peer" },
  tools: {
    profile: "messaging",
    deny: ["group:automation", "group:runtime", "group:fs", "gateway", "cron", "sessions_spawn", "sessions_send"],
    fs: { workspaceOnly: true },
    elevated: { enabled: false },
  },
  agents: {
    defaults: {
      sandbox: {
        mode: "non-main",
        scope: "session",
        workspaceAccess: "none",
      },
    },
  },
}
샌드박싱은 완벽한 경계는 아니지만, tool-enabled agent의 blast radius를 줄이는 데 가장 실용적인 방어선입니다.
  • non-main 또는 all 모드 고려
  • write가 필요 없으면 workspace를 read-only 또는 none으로
  • bind mount는 최소화
  • elevated는 예외 상황에서만

Sub-agent delegation guardrail

sub-agent를 쓸 때도 같은 원칙이 적용됩니다.
  • 비신뢰 콘텐츠를 다루는 agent에는 runtime/fs/control-plane tool을 기본 제한
  • delegation이 늘수록 session 수, tool path, memory path가 함께 늘어난다는 점 고려
  • group/session spawn 권한은 쉽게 열지 않기

Browser control risks

브라우저 제어는 단순 스크린샷 도구가 아니라 operator capability에 가깝습니다.
  • 로그인된 세션, intranet, local admin panel에 접근할 수 있음
  • browser automation은 SSRF-like pivot이 될 수 있음
  • 개인 브라우저 프로필을 재사용하지 않는 것이 좋음

Browser SSRF policy (trusted-network default)

기본값은 trusted-network에 가깝게 두고, private network 접근 허용 여부를 신중히 결정하세요.
  • browser.ssrfPolicy.dangerouslyAllowPrivateNetwork는 정말 필요할 때만 사용
  • 내부 admin panel이나 metadata endpoint에 agent가 닿지 않도록 설계

Per-agent access profiles (multi-agent)

agent마다 서로 다른 access profile을 주는 것이 가장 현실적인 하드닝 방법 중 하나입니다.
  • 대화 전용 agent
  • 읽기 전용 도구 agent
  • 강한 coding/runtime agent
  • 브라우저 전용 agent

Example: full access (no sandbox)

{
  agents: {
    list: [
      {
        id: "trusted-work",
        tools: { profile: "coding" },
        sandbox: { mode: "off" },
      },
    ],
  },
}

Example: read-only tools + read-only workspace

{
  agents: {
    list: [
      {
        id: "readonly-review",
        tools: {
          allow: ["read", "browser"],
        },
        sandbox: {
          mode: "all",
          workspaceAccess: "ro",
        },
      },
    ],
  },
}

Example: no filesystem/shell access (provider messaging allowed)

{
  agents: {
    list: [
      {
        id: "chat-only",
        tools: {
          profile: "messaging",
          deny: ["group:runtime", "group:fs", "gateway", "cron"],
        },
      },
    ],
  },
}

What to Tell Your AI

모델에게도 운영 규칙을 분명히 알려 주세요.
  • 낯선 사람에게 filesystem이나 secret를 노출하지 말 것
  • permission boundary를 넘지 말 것
  • group에서는 최소 권한으로 행동할 것
  • 확실하지 않으면 실행보다 질문을 선택할 것

Security Rules

  • 먼저 사람과 surface를 제한하고, 나중에 도구를 연다
  • open group과 powerful tool 조합을 피한다
  • 개인 계정과 공유 계정을 섞지 않는다
  • plugin, skill, browser profile은 trusted code / trusted state로 본다
  • auth, sandbox, allowlist는 “있으면 좋은 것”이 아니라 기본선이다

Incident Response

Contain

  • gateway 프로세스를 즉시 중지
  • network exposure 차단
  • 관련 node/browser session 분리

Rotate (assume compromise if secrets leaked)

  • gateway token/password 교체
  • model API key/OAuth credential 회전
  • 채널 bot token과 기타 secret도 교체

Audit

  • openclaw security audit --deep 실행
  • session log, transcript, command history를 검토
  • 어떤 surface가 열려 있었는지 재구성

Collect for a report

  • 재현 절차
  • 관련 config
  • 영향 범위와 노출된 secret 목록
  • 수정 후 재검증 결과

Secret Scanning (detect-secrets)

저장소와 설정 파일에서 secret scanning을 습관화하는 것이 좋습니다.
  • commit 전에 secret scanner 실행
  • plaintext credential이 auth profile이나 .env에 남지 않았는지 확인
  • generated file도 함께 점검

If CI fails

  • 노출된 secret를 즉시 revoke
  • 파일에서 제거 후 새 값으로 교체
  • 필요한 경우 이력 정리와 추가 보고 수행

Reporting Security Issues

실제 보안 이슈를 발견했다면 공개 이슈보다 보안 제보 경로를 우선 사용하세요. 재현 방법, 신뢰 경계, 배포 가정, 실제 영향 범위를 함께 정리하는 것이 좋습니다.