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의 위임된 도구 권한을 사실상 공유한다고 봐야 함
Quick check: openclaw security audit
참고: Formal Verification (Security Models)
config를 바꾸거나 network surface를 노출했다면 다음 명령을 정기적으로 실행하세요.
- 누가 봇과 대화할 수 있는가
- 봇이 어디에서 행동할 수 있는가
- 봇이 무엇에 접근할 수 있는가
Deployment assumption (important)
OpenClaw는 호스트와 config 경계가 신뢰된다고 가정합니다.~/.openclaw와openclaw.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 사용을 통해 유출을 유도할 수 있습니다.
Company-shared agent: acceptable pattern
같은 trust boundary 안의 팀이 업무 전용 범위로만 사용하는 agent라면 허용 가능합니다.- 전용 머신/VM/컨테이너에서 실행
- 전용 OS 사용자 + 전용 browser/profile/account 사용
- 개인 Apple/Google 계정이나 개인 password-manager/browser profile에 로그인하지 않기
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 메커니즘이 아닙니다.
Trust boundary matrix
| Boundary or control | What it means | Common misread |
|---|---|---|
gateway.auth | gateway API 호출자를 인증 | ”매 프레임마다 서명이 있어야 안전하다” |
sessionKey | context/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 ! shell | operator가 직접 트리거한 로컬 실행 | ”로컬 shell convenience가 곧 remote injection이다” |
| Node pairing / node commands | paired 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
보안 이슈를 올리기 전에 다음을 확인하세요.- 최신
main또는 최신 릴리스에서 재현되는가 - 정확한 code path(file, function, line range)와 테스트한 version/commit이 있는가
- 영향이 문서화된 trust boundary를 실제로 넘는가
- Out of Scope에 이미 해당하지 않는가
- 기존 advisory와 중복되지 않는가
- deployment assumption(local/loopback vs exposed, trusted vs untrusted operator)을 명시했는가
Hardened baseline in 60 seconds
먼저 이 기본선부터 적용하고, 그다음 신뢰된 agent별로 필요한 도구만 다시 열어 주세요.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 결과를 볼 때 우선순위는 보통 다음 순서입니다.open+ tools enabled: DM/group 노출부터 줄이고 tool policy와 sandboxing을 조정- public network exposure: LAN bind, Funnel, missing auth는 즉시 수정
- browser control remote exposure: operator access처럼 취급
- permissions: state/config/credential/auth가 group/world-readable인지 확인
- plugins/extensions: 신뢰하는 것만 로드
- model choice: tools가 있는 bot에는 최신 지시 추종성이 강한 모델 사용
Security audit glossary
실운영에서 자주 보게 되는checkId 예시:
checkId | Severity | Why it matters | Primary fix key/path | Auto-fix |
|---|---|---|---|---|
fs.state_dir.perms_world_writable | critical | 다른 사용자/프로세스가 전체 OpenClaw 상태를 수정 가능 | ~/.openclaw permission | yes |
fs.config.perms_writable | critical | 타인이 auth/tool policy/config를 바꿀 수 있음 | ~/.openclaw/openclaw.json permission | yes |
fs.config.perms_world_readable | critical | config 안의 token/setting 노출 | config file permission | yes |
gateway.bind_no_auth | critical | shared secret 없이 외부 bind | gateway.bind, gateway.auth.* | no |
gateway.loopback_no_auth | critical | reverse proxy된 loopback이 무인증으로 노출될 수 있음 | gateway.auth.*, proxy setup | no |
gateway.http.no_auth | warn/critical | auth.mode="none"으로 HTTP API 노출 | gateway.auth.mode, gateway.http.endpoints.* | no |
gateway.tools_invoke_http.dangerous_allow | warn/critical | HTTP API에서 위험한 도구를 다시 허용 | gateway.tools.allow | no |
gateway.nodes.allow_commands_dangerous | warn/critical | 고위험 node command 허용 | gateway.nodes.allowCommands | no |
gateway.tailscale_funnel | critical | 공용 인터넷 노출 | gateway.tailscale.mode | no |
gateway.control_ui.allowed_origins_required | critical | non-loopback Control UI에 origin allowlist가 없음 | gateway.controlUi.allowedOrigins | no |
gateway.control_ui.host_header_origin_fallback | warn/critical | Host header fallback으로 DNS rebinding hardening 약화 | gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback | no |
gateway.control_ui.insecure_auth | warn | insecure auth compatibility가 켜짐 | gateway.controlUi.allowInsecureAuth | no |
gateway.control_ui.device_auth_disabled | critical | device identity check 비활성화 | gateway.controlUi.dangerouslyDisableDeviceAuth | no |
gateway.real_ip_fallback_enabled | warn/critical | X-Real-IP fallback 신뢰로 source-IP spoofing 가능 | gateway.allowRealIpFallback, gateway.trustedProxies | no |
discovery.mdns_full_mode | warn/critical | mDNS full mode가 cliPath/sshPort metadata를 광고 | discovery.mdns.mode, gateway.bind | no |
config.insecure_or_dangerous_flags | warn | insecure/dangerous debug flag 활성화 | finding detail 참고 | no |
hooks.token_too_short | warn | hook ingress brute force가 쉬워짐 | hooks.token | no |
hooks.request_session_key_enabled | warn/critical | 외부 호출자가 sessionKey를 직접 선택 가능 | hooks.allowRequestSessionKey | no |
hooks.request_session_key_prefixes_missing | warn/critical | 외부 session key 형식 제한이 없음 | hooks.allowedSessionKeyPrefixes | no |
logging.redact_off | warn | 민감 정보가 로그/status로 샐 수 있음 | logging.redactSensitive | yes |
sandbox.docker_config_mode_off | warn | sandbox Docker config가 있지만 비활성 | agents.*.sandbox.mode | no |
sandbox.dangerous_network_mode | critical | sandbox Docker network가 host 또는 container:* 사용 | agents.*.sandbox.docker.network | no |
tools.exec.host_sandbox_no_sandbox_defaults | warn | sandbox가 꺼져 있을 때 exec host=sandbox가 host exec로 풀림 | tools.exec.host, agents.defaults.sandbox.mode | no |
tools.exec.host_sandbox_no_sandbox_agents | warn | agent별 exec host=sandbox도 sandbox가 꺼지면 host exec로 풀림 | agents.list[].tools.exec.host, agents.list[].sandbox.mode | no |
tools.exec.safe_bins_interpreter_unprofiled | warn | interpreter/runtime bin이 safeBins에 profile 없이 있으면 exec risk 확장 | tools.exec.safeBins, tools.exec.safeBinProfiles | no |
skills.workspace.symlink_escape | warn | workspace skills/**/SKILL.md가 workspace 밖으로 resolve됨 | workspace skills/** filesystem state | no |
security.exposure.open_groups_with_elevated | critical | open group + elevated tool은 고위험 injection 경로 | channels.*.groupPolicy, tools.elevated.* | no |
security.exposure.open_groups_with_runtime_or_fs | critical/warn | open group이 command/file tool에 접근 가능 | channels.*.groupPolicy, tools.profile/deny, tools.fs.workspaceOnly, agents.*.sandbox.mode | no |
security.trust_model.multi_user_heuristic | warn | config가 personal-assistant trust model과 어긋나 보임 | gateway 분리 또는 sandbox/tool deny/workspace scoping | no |
tools.profile_minimal_overridden | warn | agent override가 global minimal profile을 우회 | agents.list[].tools.profile | no |
plugins.tools_reachable_permissive_policy | warn | extension tool이 permissive context에서 도달 가능 | tools.profile, tool allow/deny | no |
models.small_params | critical/info | 작은 모델 + 위험한 tool surface는 injection risk를 키움 | model choice + sandbox/tool policy | no |
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 요구사항을 완화하지도 않습니다.
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=truegateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=truegateway.controlUi.dangerouslyDisableDeviceAuth=truehooks.gmail.allowUnsafeExternalContent=truehooks.mappings[<index>].allowUnsafeExternalContent=truetools.exec.applyPatch.workspaceOnly=false
dangerous* / dangerously* key 예시:
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallbackgateway.controlUi.dangerouslyDisableDeviceAuthbrowser.ssrfPolicy.dangerouslyAllowPrivateNetworkchannels.discord.dangerouslyAllowNameMatchingchannels.slack.dangerouslyAllowNameMatchingchannels.googlechat.dangerouslyAllowNameMatchingchannels.msteams.dangerouslyAllowNameMatchingchannels.irc.dangerouslyAllowNameMatchingchannels.mattermost.dangerouslyAllowNameMatchingagents.defaults.sandbox.docker.dangerouslyAllowReservedContainerTargetsagents.defaults.sandbox.docker.dangerouslyAllowExternalBindSourcesagents.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에서 온 것처럼 보이면서 자동 신뢰를 얻는 우회를 막을 수 있습니다.
trustedProxies가 설정되면 gateway는 X-Forwarded-For를 사용해 client IP를 판별합니다.
X-Real-IP는 gateway.allowRealIpFallback: true를 명시적으로 켜지 않는 한 무시됩니다.
좋은 reverse proxy 동작(들어온 forwarding header를 덮어씀):
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 결과에 따라 활성 대상이 될 수 있음
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 생성 가능
commands.restart=false는 restart action만 막습니다. gateway의 config/update action까지 막지는 않습니다.
Plugins/extensions
plugin은 gateway와 같은 프로세스 안에서 실행됩니다. trusted code로 취급하세요.- 신뢰하는 출처의 plugin만 설치
- 가능하면 명시적
plugins.allowallowlist 사용 - 활성화 전에 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를 검토
- 설치 경로:
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 전체 무시
DM session isolation (multi-user mode)
기본적으로 OpenClaw는 모든 DM을 main session으로 라우팅해 device와 channel을 넘나드는 대화 연속성을 유지합니다. 하지만 여러 사람이 DM할 수 있다면 DM session을 분리하는 것이 좋습니다.Secure DM mode (recommended)
위 설정을 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)
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"은 마지막 수단으로만 사용
- 예:
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=truehooks.mappings[<index>].allowUnsafeExternalContent=true
Prompt injection does not require public DMs
DM이 공개되지 않아도 prompt injection은 발생할 수 있습니다.- group allowlist 안의 사람이 악성 콘텐츠를 보낼 수 있음
- email, web page, attached doc, pasted transcript 모두 injection surface가 될 수 있음
- trusted sender라도 계정 탈취나 혼동된 지시를 통해 위험 입력을 보낼 수 있음
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는 보통700openclaw.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은 운영자 접근 경계의 일부로 다루기
0.6.1) Browser control via node host (recommended)
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
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)
Sandboxing (recommended)
샌드박싱은 완벽한 경계는 아니지만, 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)
Example: read-only tools + read-only workspace
Example: no filesystem/shell access (provider messaging allowed)
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
- 파일에서 제거 후 새 값으로 교체
- 필요한 경우 이력 정리와 추가 보고 수행