> For the complete documentation index, see [llms.txt](https://blog.pepperclipp.com/pepperclipp-public/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://blog.pepperclipp.com/pepperclipp-public/others/openclaw-the-ai-that-actually-does-malicious-things.md).

# OpenClaw: The AI that actually does (malicious) things

OpenClaw, as a tool, is bringing something new to people. A way to have a personal assistant that helps them with their day to day tasks, manages their day, their calendar, messages, and basically every facet of life, if it has access to do so.

OpenClaw works as a digital butler, managing different tools that help with tasks. And I think I speak for a lot of people when I say we all wanted a JARVIS-like assistant that would manage everyday mundane tasks, while we do more interesting things. Yet, I cannot help but be concerned about the risks this tool can bring to the individuals and entities using it.

This article is not throwing shade on OpenClaw, nor recommending people not to use it. Quite the contrary, as stated before, I see OpenClaw as a very valuable resource. This is a practical guide to the risks it introduces and how to use it more securely, so you can get the benefits without the exposure.

### OpenClaw as an AI Assistant

OpenClaw uses a simple architecture in which it creates a gateway that manages all connections from other nodes. Initially built as an AI Assistant that would get installed on your machine, it has quickly developed into an all-in-one AI assistant that is offered as a pre-built machine by cloud providers like[ DigitalOcean](https://www.digitalocean.com/blog/moltbot-on-digitalocean) or[ AWS Lightsail](https://aws.amazon.com/blogs/aws/introducing-openclaw-on-amazon-lightsail-to-run-your-autonomous-private-ai-agents/).

It allows connection to different[ AI Agents](https://docs.openclaw.ai/providers) and management through either operators (Web Browser, Terminal UI, etc.) or channels, which utilize different IRC and chatting tools, such as Discord and Telegram, to send questions and requests to the gateway, which in turn sends and receives them to and from the LLM Agents configured to be used by it.

To extend the functionalities of OpenClaw, skills, plugins, and commands are installed and enabled, with different features added to the gateway. Skills and plugins can be custom developed and installed. The main hub for Skills is[ ClawHub](https://clawhub.ai), with the option to install them through a GitHub repository, while Plugins can be installed through the[ npm package registry](https://www.npmjs.com/search?q=openclaw%20plugin).

All the configuration made through any operator is saved on the OpenClaw configuration file, which by default resides in the OpenClaw directory on the user’s home folder. The config file contains configuration about the LLM model used and its authentication methods, channels, plugins, tools, commands, and gateway configuration, amongst other things.

```
$ cat openclaw.json | jq “keys”

[

  “agents”,

  “auth”,

  “channels”,

  “commands”,

  “gateway”,

  “messages”,

  “meta”,

  “plugins”,

  “session”,

  “tools”,

  “wizard”

]
```

There are several LLM models allowed to be configured, each one requiring a token to be provided, which will allow the usage of the agent.

To allow remote access to OpenClaw, operators (or channels) are configured. These are chat platforms connected to OpenClaw, and by sending messages to the platform, OpenClaw will execute tasks.

### OpenClaw Risks

> "If it's easy for you, it's easy for an attacker" is a mantra I stand by when it comes to any tool or feature. If the user can come up with some hack to make their job easy, that can become a tool for an attacker.

Everything from authentication bypasses or “Remember Me” checkboxes, to autonomous tools that gather information and parse it into other formats, to IDE libraries, can be great tools that an attacker can utilize to gain access to the system or data controlled by you.

OpenClaw uses the same trust as any other trojanized app, as it is considered a trusted app, installed and managed by the identity using the machine, allowing attackers to utilize it as a malware deployment tool, evasion bypass, and botnet.

#### Plaintext credentials stored on the machine

The first issue I found was credentials stored on files inside the gateway endpoint, unencrypted. These credentials, usually part of the config file, contain tokens of channels, which allow remote access using known chat platforms, such as Telegram, Discord, and WhatsApp, along with LLM Agent access tokens, using which requests can be sent to the agents that process the information.

In the config file, the channels that are configured will require a credential to be generated, usually in the form of a bot, which will have access to the channel that is allowed to execute the tasks.

```
$ cat ~/.openclaw/openclaw.json

--snip--

“channels”: {

    “discord”: {

      “enabled”: true,

      “token”: “MTQ3******************************************”,

      “groupPolicy”: “allowlist”,

      “streaming”: “off”,

      “guilds”: {

        “80*********************”: {

          “channels”: {

            “14*********************”: {

              “allow”: true

            }

          }

        }

      }

    }

  }

--snip--

On the other hand, when an agent is configured to be used by OpenClaw, their credentials are stored in the agents directory, inside OpenClaw’s home directory.

$ cat ~/.openclaw/agents/main/agent/auth-profiles.json

{

  “version”: 1,

  “profiles”: {

    “anthropic:default”: {

      “type”: “api_key”,

      “provider”: “anthropic”,

      “key”: “sk-ant-api03-vB0*******************************************************”

    },

    “openrouter:default”: {

      “type”: “api_key”,

      “provider”: “openrouter”,

      “key”: “sk-or-v1-94f*******************************************************”

    }

  },

  “usageStats”: {

    “openrouter:default”: {

      “errorCount”: 0,

      “lastUsed”: 1773032607613

    }

  }

}

$ cat ~/.openclaw/agents/main/agent/models.json

{

  “providers”: {

    “openrouter”: {

      “baseUrl”: “<https://openrouter.ai/api/v1>”,

      “api”: “openai-completions”,

      “models”: [

        {

          “id”: “auto”,

          “name”: “OpenRouter Auto”,

          “reasoning”: false,

          “input”: [

            “text”,

            “image”

          ],

          “cost”: {

            “input”: 0,

            “output”: 0,

            “cacheRead”: 0,

            “cacheWrite”: 0

          },

          “contextWindow”: 200000,

          “maxTokens”: 8192

        }

      ],

      “apiKey”: “sk-ant-api03-vB0*******************************************************”

    }

  }

}
```

Having both the credentials of the operator and the model allows us to take control of the model and use it for our own purposes.

#### I saw what you asked yesterday

Each time a question is made to the model, OpenClaw stores it, the thought process, and the response to the agent’s sessions directory (\~/.openclaw/agents/\<agent>/sessions/\<session file>.jsonl).

Using these files, we can gather potentially important information regarding the user of OpenClaw and information regarding the tasks they will be executing.

#### Look at this old config file

When openclaw config is executed and the configuration is changed, OpenClaw will keep a copy of the old config file on the machine. This config file can contain information about other configurations, such as old keys or tokens that are still valid, which can be abused by the attacker.

#### OpenClaw as a malware delivery tool

This article is definitely[ not the first one](https://www.google.com/search?q=malicious+openclaw+skills) touching the subject of OpenClaw’s misuse by attackers as a malware delivery tool, and its users rushing to install the latest feature in the form of plugins and skills, without first making sure what they are installing is legitimate.

The skill and plugins are where things get particularly interesting from an attacker’s perspective. Skills are just markdown files sitting in a local workspace directory, and because OpenClaw loads and executes them with essentially no verification, coercing the user into installing a malicious skill will allow the attacker to gain execution on both the agent and the system. It becomes worse when skills can contain dependencies that may contain malicious code being installed on the machine.

Plugins make this even worse. Plugins are essentially TypeScript code used by OpenClaw on the machine. It will get executed on the machine, using the permissions of the identity executing OpenClaw, and run the code containing anything in its body. This means that an attacker can inject malicious code into the plugin and make the code execute each time the gateway starts with the elevated permissions of the user.

**Skills**

Skills are user input commands that teach OpenClaw how to combine tools to accomplish tasks. OpenClaw offers 50+[ official skills](https://github.com/openclaw/openclaw/tree/main/skills) covering notes, email, social media, development, and more.

```
{

  “skills”: {

    “allowBundled”: [

      “gog”, “github”, “tmux”, “session-logs”,

      “weather”, “summarize”, “clawhub”,

      “healthcheck”, “skill-creator”

    ]

  }

}
```

Every skill is a directory containing at a minimum a SKILL.md file. The SKILL.md explains which environment variables are required and when the agent should call the associated script. At the next startup, the agent reads the SKILL.md and knows, for example: “When I need to interact with ClickUp, use this skill.”

Skills use[ agent skills](https://github.com/anthropics/skills) as a technology, where the SKILL.md file will contain all the instructions for the agent to run, and then have scripts, documentation, and other assets to assist with the task required.

```
my-skill/

├── SKILL.md                         # Required - main skill file

├── scripts/                         # Optional - executable code

│ ├── process_data.py

│ └── validate.sh

├── references/                      # Optional - documentation

│ ├── api-guide.md

│ └── examples/

└── assets/                          # Optional - templates, etc.

└── report-template.md
```

Each skill will contain some headers, such as name, description, and homepage, but OpenClaw also adds the OpenClaw Metadata, which adds other elements used by OpenClaw. One of these elements is the path of installation for dependencies. This JSON block will contain the source of the installed module, the runtime, and the binaries that will be installed on the machine.

```


name: Skill Name

description: A most definetly non-malicious skill

homepage: <https://domain.tld>

metadata:

  {

    “openclaw”:

      {

        “emoji”: “☣️”,

        “requires”: { “bins”: [”<binary>”] },

        “install”:

          [

            {

              “id”: “go”,

              “kind”: “go”,

              “module”: “github.com/<gh account>/<repo>/<path>@latest”,

              “bins”: [”<bin name>”],

              “label”: “Install binary (go)”,

            },

          ],

      },

  }
```

```
# testbin (tb)

Use `tb` to interact with testbin.

## Quick start

- `tb --help`

- `tb run <task>`

## Target selection (in priority order)

- `--target <id|name|alias>`

- `TESTBIN_TARGET`

- config default (if set)

## Common tasks

- Status: `tb status`

- Run a task: `tb run “task name”`

- List available tasks: `tb list`

- Stop a task: `tb stop <id>`
```

Prefer \`--json\` for scripts. Confirm the target before making changes.

This is the injection point. An attacker who controls the skill can specify a malicious binary in the install block. When the user installs the skill, that binary runs, giving the attacker execution on the machine.

**Plugins**

Where skills teach the agent what to do, plugins extend what the gateway itself can do. They are Node.js modules that hook directly into the gateway and offer new features, like registering new channels, adding event listeners, or wiring up new transport layers.

By default, OpenClaw comes with a list of stock plugins that are stored in the extensions directory of the OpenClaw Node module directory.

`$ openclaw plugins list`

```
🦞 OpenClaw 2026.3.2 (85377a2) — I can run local, remote, or purely on vibes—results may vary with DNS.

Plugins (6/38 loaded)

Source roots:

  stock: **/home/user/.npm-global/lib/node_modules/openclaw/extensions**

┌──────────────┬──────────┬──────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────┐

│ Name         │ ID       │ Status   │ Source                                                                                                  │ Version  │

├──────────────┼──────────┼──────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┤

│ ACPX Runtime │ acpx     │ disabled │ stock:acpx/index.ts                                                                                     │ 2026.3.2 │

│              │          │          │ ACP runtime backend powered by acpx with configurable command path and version policy.                  │          │

│ @openclaw/   │ bluebubb │ disabled │ stock:bluebubbles/index.ts                                                                              │ 2026.3.2 │

│ bluebubbles  │ les      │          │ OpenClaw BlueBubbles channel plugin                                                                     │          │

│ @openclaw/   │ copilot- │ disabled │ stock:copilot-proxy/index.ts                                                                            │ 2026.3.2 │

│ copilot-     │ proxy    │          │ OpenClaw Copilot Proxy provider plugin                                                                  │          │

│ proxy        │          │          │                                                                                                         │          │

│ Device       │ device-  │ loaded   │ stock:device-pair/index.ts                                                                              │          │

│ Pairing      │ pair     │          │ Generate setup codes and approve device pairing requests.                                               │          │

│ @openclaw/   │ diagnost │ disabled │ stock:diagnostics-otel/index.ts                                                                         │ 2026.3.2 │

│ diagnostics- │ ics-otel │          │ OpenClaw diagnostics OpenTelemetry exporter                                                             │          │

│ otel         │          │          │                                                                                                         │          │

│ Diffs        │ diffs    │ disabled │ stock:diffs/index.ts                                                                                    │ 2026.3.2 │

│              │          │          │ Read-only diff viewer and file renderer for agents.                                                     │          │

│ Discord      │ discord  │ loaded   │ stock:discord/index.ts                                                                                  │ 2026.3.2 │

│              │          │          │ Discord channel plugin                                                                                  │          │

--snip--
```

OpenClaw offers the possibility of[ creating custom plugins](https://docs.openclaw.ai/plugins/building-plugins), written in TypeScript, which can offer basically any feature that is possible to be coded, such as new channels, connection to external services, and potentially a Command and Control beacon. This becomes a problem for security, as an attacker can coerce the user into installing a plugin, infect a legitimate one, or even modify one residing on the machine for persistence.

Aside from installing, plugins also need to be enabled in the config file in the plugins section. A plugin not enabled will not be executed by OpenClaw.

```
“plugins”: {

  “entries”: {

    “discord”: {

      “enabled”: true

    },

    “telegram”: {

      “enabled”: true

    },

    **”gotcha”: {

      “enabled”: true   # The custom plugin installed by the user/attacker

    }**

  }

}
```

#### OpenClaw as a persistence mechanism

Local machine persistence was covered in the malicious plugins section, but it is not the only goal an attacker might have. Some attackers are only interested in the agent itself, such as using it for unethical content creation, attacking other targets, or exploiting the knowledge and access the agent holds over the user’s life, information, and work.

**Modifying the config file to tamper with the gateway**

OpenClaw offers the command openclaw configure, which allows configuration of the gateway using an interactive terminal GUI. This command updates the config file and even puts a metadata timestamp of the config file’s update time. The metadata timestamp is confirmed not to be used as a logging mechanism, just metadata. Later on, in the logs section, we can see how to actually detect a config file update.

```
$ head -n 5 openclaw.json

{

  “meta”: {

    “lastTouchedVersion”: “2026.3.2”,

    “lastTouchedAt”: “2026-03-06T22:43:47.297Z”

  },
```

One other thing I noticed is that updating the config file directly, without using \`openclaw configure\`, and restarting the gateway will still apply those configuration changes on the gateway. The config file resides on the home directory of the user executing it, in the .openclaw directory, and is readable and writable from the user running it. No special permissions are required.

```
$ ls -la ~/.openclaw/openclaw.json

-rw------- 1 user user 2855 Mar  6 23:43 /home/user/.openclaw/openclaw.json
```

At the same time, the gateway is restartable by the identity running OpenClaw. And in cases when OpenClaw is installed on the user’s machine, it will be the user who will have those privileges.

```
diff old_openclaw.json new_openclaw.json

# at channels

“telegram”: {

 “enabled”: true,

 “dmPolicy”: “pairing”,

 “botToken”: “87********:AAF**************************”,

 “groupPolicy”: “allowlist”,

 “streaming”: “partial”

},

# At plugins

“telegram”: {

 “enabled”: true

},
```

That means an attacker can update the config file, as allowed, restart the gateway as allowed, and set a channel to access the AI agent, maintaining persistence.

**Add a new channel**

Extending on the previous section, if an attacker wants access to OpenClaw, they can add a new channel, such as a Telegram bot, to the config file and restart the gateway. This will configure the gateway to be accessed by that channel, which will allow the attacker remote access to OpenClaw.

```
“channels”: {

    “telegram”: {

      “enabled”: true,

      “dmPolicy”: “pairing”,

      “botToken”: “87******:AAG***************************”,

      “groupPolicy”: “allowlist”,

      “streaming”: “partial”

    }

  }

Channels operate using plugins, so they will need to be enabled in the config file.

“plugins”: {

	“telegram”: {

		“enabled”: true

	}

}
```

Before the channel can be allowed to be used, it needs to be allowed to pair on the gateway, and the configuration is done and ready for remote access.

```
~/.openclaw$ openclaw channels list

--snip--

Chat channels:

**- Telegram default: configured, token=config, enabled**

**-** Discord default: configured, token=config, enabled

--snip--
```

#### Accessing the LLM model directly

When we talked about credentials being stored as plaintext on the machine, one of the credentials we spoke about was the LLM model’s token. The token is needed as OpenClaw does no more than programmatic access on the model, sending and receiving prompts.

An attacker with those credentials stolen can create a simple prompt request-response script that will send questions and receive answers from the model and abuse the target’s model and money for any activity they need to execute.

**OpenClaw as a botnet**

Between February 21 and March 2, 2026, a hacking bot calling itself[ hackerbot-claw started targeting vulnerable GitHub Workflows](https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation), an incident[ we also wrote about](https://www.exaforce.com/blogs/hackerbot-claw-research). The bot was taken down, and the repository it was using was as well, but while it was up, it managed to breach several repositories, access their workflow credentials, and even push unauthorized code.

Botnets are not new. Compromised machines being used for DDoS attacks or as pivot points is a well-understood threat. But the model assumes dumb bots executing fixed instructions. What happens when the bots are autonomous agents that can target environments, adapt to defenses, execute attacks, and cover the attacker’s tracks?

And what happens when that agent is actually your agent? We looked at how we can get access to the agent either through stealing credentials of the agent stored on the OpenClaw gateway or persisting using another operator. An attacker with this access can utilize the agent, make it the bot as part of the botnet, cost you money, and indirectly make you a complice on a specific attack.

Don’t get me wrong, this is not an OpenClaw only issue. Gaining access to an LLM-powered project and abusing the agent’s tokens to utilize it can happen to anybody with that setup, but OpenClaw is another project that allows this attack. That means constant monitoring of changes to the gateway configurations and prevention of unwanted access to the gateway will need to be a high priority.

### Detecting if a user is using OpenClaw

Since OpenClaw has its own attack surface, it is important to know which identities are using it and how. That means, what plugins and skills are they installing, what skills tools are they enabling, and what channels are they configuring. There are several ways to know if OpenClaw is installed and running on a machine, but they depend on whether the target is installing OpenClaw as a gateway locally or using a remote gateway with the machine being a node.

OpenClaw is a NodeJS module, whose source code can be found in Node’s NPM modules directory. There lies the source code of the actual package that will be executed. The package will also contain the terminal tool openclaw that can be used to configure the gateway and operate the agent.

```
$ which openclaw

/home/user/.npm-global/bin/openclaw

$ ls -la .npm-global/lib/node_modules/openclaw/

total 776

drwxr-xr-x   8 user user   4096 Mar  3 21:44 .

drwxr-xr-x   3 user user   4096 Mar  3 21:43 ..

-rw-r--r--   1 user user 561549 Mar  3 21:44 CHANGELOG.md

-rw-r--r--   1 user user   1074 Mar  3 21:44 LICENSE

-rw-r--r--   1 user user 122711 Mar  3 21:44 README.md

drwxr-xr-x   3 user user   4096 Mar  3 21:44 assets

drwxr-xr-x   8 user user  36864 Mar  3 21:44 dist

drwxr-xr-x  28 user user   4096 Mar  3 21:44 docs

drwxr-xr-x  43 user user   4096 Mar  3 21:44 extensions

-rwxr-xr-x   1 user user   2311 Mar  3 21:44 openclaw.mjs

-rw-r--r--   1 user user  15243 Mar  3 21:44 package.json

drwxr-xr-x  54 user user   4096 Mar  3 21:44 skills
```

If the gateway is installed locally, the gateway’s files, such as the config files, skills, plugins, credentials, prompts for the agent, etc, will be stored in the home directory of the user running OpenClaw, in the directory .openclaw.

```
$ ls -la .openclaw/

total 96

drwx------ 14 user user 4096 Apr  7 23:37 .

drwxr-x--- 11 user user 4096 Apr  7 23:18 ..

drwxr-xr-x  3 user user 4096 Mar  3 22:05 agents

drwxrwxr-x  2 user user 4096 Mar  4 21:18 canvas

drwxr-xr-x  2 user user 4096 Mar  3 22:06 completions

drwx------  2 user user 4096 Mar  6 22:45 credentials

drwxrwxr-x  2 user user 4096 Mar  4 21:18 cron

drwxrwxr-x  2 user user 4096 Apr  7 23:13 devices

-rw-------  1 user user  378 Mar  8 07:06 exec-approvals.json

drwxr-xr-x  3 user user 4096 Apr  7 23:09 extensions

drwxr-xr-x  2 user user 4096 Mar  4 21:19 identity

drwx------  2 user user 4096 Mar  3 22:06 logs

drwxr-xr-x  2 user user 4096 Mar  3 22:06 memory

-rw-------  1 user user 2939 Apr  7 23:37 openclaw.json

drwxrwxr-x  2 user user 4096 Apr  7 22:51 telegram

-rw-------  1 user user  187 Apr  7 16:42 update-check.json

drwxr-xr-x  5 user user 4096 Apr  7 22:33 workspace

On the gateway’s machine, by default, the openclaw-gateway service will be running, associated with the process that executes the OpenClaw terminal tool.

$ ps aux | grep openclaw

user        5417  0.0  1.4 1015712 58320 pts/0   Tl   23:13   0:00 openclaw

user        5424  0.1  7.2 1349908 288108 pts/0  Tl   23:13   0:04 openclaw

**user        6604  7.7 10.1 22575616 403304 ?     Ssl  23:53   0:18 openclaw-gateway**

user        6763 50.0  0.0   4092  2048 pts/0    S+   23:57   0:00 grep --color=auto openclaw

$ systemctl status

--snip--

```

```
user.slice

	└─user-1000.slice

	 ├─session-1.scope

	 │ ├─180 /bin/login -f

	 │ └─322 -bash

	 └─user@1000.service

	   ├─app.slice

	   **│ └─openclaw-gateway.service

	   │   └─6604 openclaw-gateway**

	   └─init.scope

	     ├─273 /usr/lib/systemd/systemd --user

	     └─279 “(sd-pam)

--snip--
```

The gateway by default runs on ports \`18789\`, where \`18789\` is also used as the web service for the browser based controller.

```
$ netstat -auntp

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

tcp        0      0 127.0.0.1:18792         0.0.0.0:*               LISTEN      6604/openclaw-gatew

tcp        0      0 127.0.0.1:18789         0.0.0.0:*               LISTEN      6604/openclaw-gatew

tcp        0      0 127.0.0.1:18791         0.0.0.0:*               LISTEN      6604/openclaw-gatew

--snip--
```

```
$ cat ~/.openclaw/openclaw.json

--snip--

“gateway”: {

  “port”: 18789,

  “mode”: “local”,

  “bind”: “loopback”,

  “auth”: {

    “mode”: “token”,

    “token”: “******************************************”

  },

  “tailscale”: {

    “mode”: “off”,

    “resetOnExit”: false

  }

}

--snip--
```

Lastly, in the temporary directory, there will be two OpenClaw directories, one containing the gateway logs and another a metadata file for the gateway.

```
**$ ls /tmp/openclaw***

/tmp/openclaw:

openclaw-2026-04-07.log

/tmp/openclaw-1000:

gateway.a1f21f5b.lock
```

### Detecting OpenClaw misuse by an attacker

This step is a bit long, as we will need to look for several angles, to find if an attacker is misusing OpenClaw or has attempted to misuse it. We will need to look for skills and plugins installed, config file tampering, prompt and gateway logging, as well as cost as a monitoring metric.

#### Use gateway information messages

One feature I like from OpenClaw is the verbosity the gateway has on restart. It will list channels, plugins, bad practices, and even warnings on misconfigurations. This is an important feature for initial detection methods, as gateway restart might be more common than many other commands being executed on the gateway.

```
~/.openclaw$ openclaw gateway restart

🦞 OpenClaw 2026.3.2 (85377a2) — Your personal assistant, minus the passive-aggressive calendar reminders.

│

◇  Doctor warnings ──────────────────────────────────────────────────────────────────────────╮

│                                                                                            │

│  - channels.telegram.groupPolicy is “allowlist” but groupAllowFrom (and allowFrom) is      │

│    empty — all group messages will be silently dropped. Add sender IDs to                  │

│    channels.telegram.groupAllowFrom or channels.telegram.allowFrom, or set groupPolicy to  │

│    “open”.                                                                                 │

│                                                                                            │

├────────────────────────────────────────────────────────────────────────────────────────────╯

│

◇  Doctor warnings ───────────────────────────────────────────────────────────────────╮

│                                                                                     │

│  - tools.exec.safeBins includes interpreter/runtime ‘bash’ without profile.         │

│  - Run “openclaw doctor --fix” to scaffold missing custom safeBinProfiles entries.  │

│                                                                                     │

├─────────────────────────────────────────────────────────────────────────────────────╯

Restarted systemd service: openclaw-gateway.service

Other checks that can be done periodically include running openclaw doctor and openclaw security audit, which respectively check for misconfigurations and security issues on the gateway. Between them, they surface new plugins and skills, configured channels, misconfigurations, and signs of abuse.

$ openclaw doctor

--snip--

◇  Doctor warnings ──────────────────────────────────────────────────────────────────────────╮

│                                                                                            │

│  - channels.telegram.groupPolicy is “allowlist” but groupAllowFrom (and allowFrom) is      │

│    empty — all group messages will be silently dropped. Add sender IDs to                  │

│    channels.telegram.groupAllowFrom or channels.telegram.allowFrom, or set groupPolicy to  │

│    “open”.                                                                                 │

│                                                                                            │

├────────────────────────────────────────────────────────────────────────────────────────────╯

│

◇  Doctor warnings ───────────────────────────────────────────────────────────────────╮

│                                                                                     │

│  - tools.exec.safeBins includes interpreter/runtime ‘bash’ without profile.         │

│  - Run “openclaw doctor --fix” to scaffold missing custom safeBinProfiles entries.  │

│                                                                                     │

├─────────────────────────────────────────────────────────────────────────────────────╯

│

◇  Skills status ────────────╮

│                            │

│  Eligible: 6               │

│  Missing requirements: 46  │

│  Blocked by allowlist: 0   │

│                            │

├────────────────────────────╯

│

◇  Plugins ──────╮

│                │

│  Loaded: 6     │

│  Disabled: 32  │

│  Errors: 1     │

│  - gotcha      │

│                │

├────────────────╯

--snip--

$ openclaw security audit --deep

--snip--

│

◇  Doctor warnings ──────────────────────────────────────────────────────────────────────────╮

│                                                                                            │

│  - channels.telegram.groupPolicy is “allowlist” but groupAllowFrom (and allowFrom) is      │

│    empty — all group messages will be silently dropped. Add sender IDs to                  │

│    channels.telegram.groupAllowFrom or channels.telegram.allowFrom, or set groupPolicy to  │

│    “open”.                                                                                 │

│                                                                                            │

├────────────────────────────────────────────────────────────────────────────────────────────╯

│

◇  Doctor warnings ───────────────────────────────────────────────────────────────────╮

│                                                                                     │

│  - tools.exec.safeBins includes interpreter/runtime ‘bash’ without profile.         │

│  - Run “openclaw doctor --fix” to scaffold missing custom safeBinProfiles entries.  │

│                                                                                     │

├─────────────────────────────────────────────────────────────────────────────────────╯

OpenClaw security audit

Summary: 0 critical · 4 warn · 1 info

Run deeper: openclaw security audit --deep

WARN

gateway.trusted_proxies_missing Reverse proxy headers are not trusted

  gateway.bind is loopback and gateway.trustedProxies is empty. If you expose the Control UI through a reverse proxy, configure trusted proxies so local-client checks cannot be spoofed.

  Fix: Set gateway.trustedProxies to your proxy IPs or keep the Control UI local-only.

tools.exec.safe_bins_interpreter_unprofiled safeBins includes interpreter/runtime binaries without explicit profiles

  Detected interpreter-like safeBins entries missing explicit profiles:

- tools.exec.safeBins: bash

These entries can turn safeBins into a broad execution surface when used with permissive argv profiles.

  Fix: Remove interpreter/runtime bins from safeBins (prefer allowlist entries) or define hardened tools.exec.safeBinProfiles.<bin> rules.

tools.exec.safe_bin_trusted_dirs_risky safeBinTrustedDirs includes risky mutable directories

  Detected risky safeBinTrustedDirs entries:

- tools.exec.safeBinTrustedDirs: ~/.trustedbins (relative path (trust boundary depends on process cwd))

  Fix: Prefer root-owned immutable bins, keep default trust dirs (/bin, /usr/bin), and avoid trusting temporary/home/package-manager paths unless tightly controlled.

security.trust_model.multi_user_heuristic Potential multi-user setup detected (personal-assistant model warning)

  Heuristic signals indicate this gateway may be reachable by multiple users:

- channels.discord.groupPolicy=”allowlist” with configured group targets

No unguarded runtime/process tools were detected by this heuristic.

No unguarded runtime/filesystem contexts detected.

OpenClaw’s default security model is personal-assistant (one trusted operator boundary), not hostile multi-tenant isolation on one shared gateway.

  Fix: If users may be mutually untrusted, split trust boundaries (separate gateways + credentials, ideally separate OS users/hosts). If you intentionally run shared-user access, set agents.defaults.sandbox.mode=”all”, keep tools.fs.workspaceOnly=true, deny runtime/fs/web tools unless required, and keep personal/private identities + credentials off that runtime.

INFO

summary.attack_surface Attack surface summary

  groups: open=0, allowlist=2

tools.elevated: enabled

hooks.webhooks: disabled

hooks.internal: disabled

browser control: enabled

trust model: personal assistant (one trusted operator boundary), not hostile multi-tenant on one shared gateway
```

#### Finding new plugins installed

There are two good ways to know if a plugin is installed and enabled. One is to look into the config file, under the plugins section. This is a section that contains the list of plugins and their status.

```
“plugins”: {

  “entries”: {

    “discord”: {

      “enabled”: true

    },

    “telegram”: {

      “enabled”: true

    },

    “gotcha”: {

      “enabled”: true

    }

  }

}
```

The other one is to run openclaw plugins list. It will generate a list of plugins installed, enabled, and those failing due to errors in the plugin.

```
$ openclaw plugins list

Plugins (6/39 loaded)

Source roots:

  **stock: /home/user/.npm-global/lib/node_modules/openclaw/extensions

  global: /home/user/.openclaw/extensions**

┌──────────────┬──────────┬──────────┬───────────────────────────────────────────────────────────────────────────────────────────────┬──────────┐

│ Name         │ ID       │ Status   │ Source                                                                                        │ Version  │

├──────────────┼──────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────────────────┼──────────┤

--snip--

│ synology-    │ -chat    │          │ Synology Chat channel plugin for OpenClaw                                                     │          │

│ chat         │          │          │                                                                                               │          │

│ Talk Voice   │ talk-    │ loaded   │ stock:talk-voice/index.ts                                                                     │          │

│              │ voice    │          │ Manage Talk voice selection (list/set).                                                       │          │

│ Telegram     │ telegram │ loaded   │ stock:telegram/index.ts                                                                       │ 2026.3.2 │

│              │          │          │ Telegram channel plugin                                                                       │          │

│ Thread       │ thread-  │ disabled │ stock:thread-ownership/index.ts                                                               │          │

│ Ownership    │ ownershi │          │ Prevents multiple agents from responding in the same Slack thread. Uses HTTP calls to the     │          │

│              │ p        │          │ slack-forwarder ownership API.                                                                │          │

│ @openclaw/   │ tlon     │ disabled │ stock:tlon/index.ts                                                                           │ 2026.3.2 │

│ tlon         │          │          │ OpenClaw Tlon/Urbit channel plugin                                                            │          │

│ @openclaw/   │ twitch   │ disabled │ stock:twitch/index.ts                                                                         │ 2026.3.2 │

│ twitch       │          │          │ OpenClaw Twitch channel plugin                                                                │          │

│ @openclaw/   │ voice-   │ disabled │ stock:voice-call/index.ts                                                                     │ 2026.3.2 │

│ voice-call   │ call     │          │ OpenClaw voice-call plugin                                                                    │          │

│ @openclaw/   │ whatsapp │ disabled │ stock:whatsapp/index.ts                                                                       │ 2026.3.2 │

│ whatsapp     │          │          │ OpenClaw WhatsApp channel plugin                                                              │          │

│ @openclaw/   │ zalo     │ disabled │ stock:zalo/index.ts                                                                           │ 2026.3.2 │

│ zalo         │          │          │ OpenClaw Zalo channel plugin                                                                  │          │

│ @openclaw/   │ zalouser │ disabled │ stock:zalouser/index.ts                                                                       │ 2026.3.2 │

│ zalouser     │          │          │ OpenClaw Zalo Personal Account plugin via native zca-js integration                           │          │

│ Gotcha       │ gotcha   │ error    │ global:openclaw-plugin-gotcha/index.ts                                                        │ 1.0.0    │

│              │          │          │ Writes current user info to gotcha.txt in the home directory.                                 │          │

└──────────────┴──────────┴──────────┴───────────────────────────────────────────────────────────────────────────────────────────────┴──────────┘

The plugins can be found in the home directory or the NPM package directory, as seen by the command output.

Plugins (6/39 loaded)

Source roots:

  **stock: /home/user/.npm-global/lib/node_modules/openclaw/extensions

  global: /home/user/.openclaw/extensions**
```

#### New skills installed on the machine

OpenClaw offers the command openclaw skills list as a way to list the skills installed. It will list the current skills, both stock and custom, and will show their status.

```
$ openclaw skills list

--snip--

Skills (6/52 ready)

--snip--

│ ✓ ready   │ 🌤️ weather       │ Get current weather and forecasts via wttr.in or Open-Meteo. Use when: user asks about    │ openclaw-bundled   │

│           │                  │ weather, temperature, or forecasts for any location. NOT for: historical weather data,    │                    │

│           │                  │ severe weather alerts, or detailed meteorological analysis. No API key needed.            │                    │

│ ✗ missing │ 𝕏 xurl           │ A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when  │ openclaw-bundled   │

│           │                  │ you need to post tweets, reply, quote, search, read posts, manage followers, send DMs,    │                    │

│           │                  │ upload media, or interact with any X API v2 endpoint.                                     │                    │

**│ ✓ ready   │ ☣️ Test Skill    │ A most definetly non-malicious skill. Trust me bro**                                        │ openclaw-workspace │

└───────────┴──────────────────┴───────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┘
```

We can also check the source code of the custom installed skills in the skills directory under the workspace directory (.openclaw/workspace/skills), to check what instructions or dependencies they will have and install on the machine.

```
$ ls .openclaw/workspace/skills/ -la

total 12

drwxr-xr-x 3 user user 4096 Mar  3 23:53 .

drwxr-xr-x 5 user user 4096 Apr  7 22:33 ..

drwxr-xr-x 2 user user 4096 Apr  7 21:54 some-skill
```

#### New channels configured on the gateway

This is the same as any other command we’ve seen so far. OpenClaw offers a stock command that lists configured channels on the gateway. Check them for new channels that can have been configured on the gateway, which can allow access to manage the gateway remotely.

```
$ openclaw channels list

--snip--

01:49:40 [plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load: gotcha (/home/user/.openclaw/extensions/openclaw-plugin-gotcha/index.ts). Set plugins.allow to explicit trusted ids.

Chat channels:

**- Telegram default: configured, token=config, enabled

- Discord default: configured, token=config, enabled**

Channels can also be found configured under the OpenClaw configuration file, alongside the tokens of the bots that they will be using.

“channels”: {

  “telegram”: {

    “enabled”: true,

    “dmPolicy”: “pairing”,

    “botToken”: “87******:AA**************************************”,

    “groupPolicy”: “allowlist”,

    “streaming”: “partial”

  },

  “discord”: {

    “enabled”: true,

    “token”: “MT*******************************************E”,

    “groupPolicy”: “allowlist”,

    “streaming”: “off”,

    “guilds”: {

      “809***********************”: {

        “channels”: {

          “14******************8”: {

            “allow”: true

          }

        }

      }

    }

  }

}

```

#### May I also recommend the old config file?

Attackers are not the only ones who can read old config files. If an attacker has modified the config file for the gateway and left the old one on the machine, a defender can check to see what configuration changes were made by the attacker.

Though attackers are more careful in these cases, as they are supposed to be the ones trying to hide activity, it is not uncommon to see mistakes happening from them.

#### I saw what you asked yesterday again

The prompt logging mentioned earlier as an enumeration technique was initially built to be a monitoring mechanism. We can utilize this mechanism to read malicious prompts and how the agent responded to them, so we can detect misuse of OpenClaw and potential attempts to maliciously utilize the agent.

````
{

  “type”: “message”,

  “id”: “73d90eb3”,

  “parentId”: “d564c7a1”,

  “timestamp”: “2026-03-06T22:31:00.491Z”,

  “message”: {

    “role”: “user”,

    “content”: [

      {

        “type”: “text”,

        “text”: “Sender (untrusted metadata):\\n```json\\n{\\n  \\”label\\”: \\”openclaw-control-ui\\”,\\n  \\”id\\”: \\”openclaw-control-ui\\”\\n}\\n```\\n\\n[Fri 2026-03-06 22:31 UTC] exec whoami”

      }

    ],

    “timestamp”: 1772836260488

  }

}
````

#### Use logging

OpenClaw uses JSON logging to give you visibility into what the gateway is doing at runtime. Logs are written to \~/.openclaw/logs/ by default and are invaluable for diagnosing config reload issues, plugin failures, and unexpected agent behavior.

```
{

  **”0”: “{\\”subsystem\\”:\\”gateway/reload\\”}”,

  “1”: “config change requires gateway restart (plugins.entries.telegram)”,**

  “_meta”: {

    “runtime”: “node”,

    “runtimeVersion”: “22.22.0”,

    “hostname”: “unknown”,

    “name”: “{\\”subsystem\\”:\\”gateway/reload\\”}”,

    “parentNames”: [

      “openclaw”

    ],

    **”date”: “2026-03-09T15:50:12.679Z”,

    “logLevelId”: 4,

    “logLevelName”: “WARN”,**

    “path”: {

      “fullFilePath”: “file:///home/user/.npm-global/lib/node_modules/openclaw/dist/subsystem-BfkFJ4uQ.js:427:14”,

      “fileName”: “subsystem-BfkFJ4uQ.js”,

      “fileNameWithLine”: “subsystem-BfkFJ4uQ.js:427”,

      “fileColumn”: “14”,

      “fileLine”: “427”,

      “filePath”: “.npm-global/lib/node_modules/openclaw/dist/subsystem-BfkFJ4uQ.js”,

      “filePathWithLine”: “.npm-global/lib/node_modules/openclaw/dist/subsystem-BfkFJ4uQ.js:427”,

      “method”: “logToFile”

    }

  },

  **”time”: “2026-03-09T15:50:12.680+00:00”**

}

Every log line contains three important main fields:





The message tag (field “0”) and title fields typically hold the subsystem tag (gateway/reload), and “1” holds a title/description of the event being triggered



“0”: “{\\”subsystem\\”:\\”gateway/reload\\”}”,

“1”: “config change requires gateway restart (plugins.entries.telegram)”,





_meta block, which contains several important fields that offer information about the event:







logLevelId and logLevelName contain the risk level of the event being triggered, from



**”logLevelId”: 4,

“logLevelName”: “WARN”,**





ID

Name

When you’ll see it

2

DEBUG

Verbose internal state (disabled by default)

3

INFO

Normal operational events

4

WARN

Something needs attention, but isn’t broken

5

ERROR

A failure occurred — action usually required





date, which contains the timestamp of the event
```

Some events of interest include config change, provider attachment, and tool enabling. In the logs below, for example, OpenClaw detected a config file change and started evaluating which parts of the gateway needed to react (contextPruning, heartbeat, channels.telegram, plugins.entries.telegram, tools.exec.safeBinTrustedDirs). After evaluation, it determined that the plugins.entries.telegram change is not applied and requires a gateway restart. This is a common pattern when editing openclaw\.json while the server is running.

```
“1”: “config change applied (dynamic reads: agents.defaults.models.openrouter/auto.alias)”,

“1”: “config change applied (dynamic reads: tools.exec.safeBinTrustedDirs)”,

“1”: “config change detected; evaluating reload (agents.defaults.contextPruning, agents.defaults.heartbeat)”,

“1”: “config change detected; evaluating reload (agents.defaults.models.openrouter/auto.alias)”,

“1”: “config change detected; evaluating reload (tools.exec.safeBinTrustedDirs, channels.telegram, plugins.entries.telegram)”,

“1”: “config change requires gateway restart (channels.telegram, plugins.entries.telegram)”,

After restarting, if a specific provider is started, it will be listed on the logs, meaning it will be a good indicator to look for.

“1”: “[default] starting provider (@bot147959*************)”,

“1”: “[default] starting provider (@openclaw****************)”,

“1”: “logged in to discord as 1479596065492570213 (bot147959*************)”,

“1”: “discord channels resolved: 80976**************/1479592**************→80976**************/1479592************** (guild:user’s server; channel:openclaw-commands)”,

```

Lastly, if a tool is enabled, it will be listed. Always check for new tools that were not enabled by you.

```
“1”: “config change detected; evaluating reload (tools.exec.safeBinTrustedDirs)”,

“1”: “Browser control listening on <http://127.0.0.1:18791/> (auth=token)”,
```

### Defending from misuse of OpenClaw

OpenClaw, like any software, has vulnerabilities. Code injection, memory corruption, vulnerable dependencies, and architectural weaknesses have all been found before, and more will be. Some of those will be discovered by threat actors before they are found and patched.

One of those vulnerabilities[ was found and fixed](https://www.oasis.security/blog/openclaw-vulnerability) in February 2026 by Oasis Security, and it is neither the first nor the last vulnerability to be found. So, always consider that an app is code and code can be vulnerable.

#### Use the malware scanners

One feature that is important to look into is the skill scanner from ClawHub. ClawHub will utilize VirusTotal to scan for malicious skills uploaded to it and provide a response to how benign or malicious something can be.

It should be noted that writing malware that bypasses all antivirus solutions currently scanning for VirusTotal is not impossible. There is a whole sub-field in Red-Teaming of malware writers specializing in bypassing security solutions to execute malware on machines with antivirus and EDR, but it is still a good idea to look into the scanning it provides, as an initial awareness.

#### You shall not be used

OpenClaw’s config file supports allow and deny lists for tools and plugins. Anything not explicitly enabled is loaded but blocked from executing. Review the config regularly for tools and plugins you did not configure, and disable anything unfamiliar.

```
{

  tools: {

	  deny: [”browser”]

	},

	“plugins”: {

  “entries”: {

    “discord”: {

      “enabled”: true

    },

    “telegram”: {

      “enabled”: true

    },

    **”gotcha”: {

      “enabled”: false

    }**

  }

}
```

#### Use the source, Luke

While speaking with more technical users, getting comfortable reading and understanding the source code of skills and plugins, before installing or enabling them, can help a lot with security.

Skills themselves are easier than plugins, as they are just directories containing a SKILL.md file and accompanying scripts, while plugins are Node.js modules wired into the gateway, they’re generally readable even without deep programming experience. SKILL.md describes what the skill is ordered to do, in human readable text, and what tools it exposes to the agent. Then look at the actual script files to verify that what the code does matches what the description says. Pay particular attention to any outbound network calls (fetch, axios, http.request), file system access (fs.readFile, fs.writeFile), and shell executions (exec, spawn), as these are the three actions that can cause real harm if a skill is malicious or poorly written.

For plugins, check what channels or hooks they register into and whether they read from sensitive config fields like API tokens or credentials. You don’t need to understand every line, as you’re mostly looking for anything that sends data somewhere unexpected or touches parts of your system that the skill has no legitimate reason to access. Given that we are seeing that a significant portion of community skills and plugins contain vulnerabilities or malicious code, spending some time on a quick code read can save you from a serious security incident.

#### Use sandboxing as much as possible

OpenClaw’s sandbox is a contained environment wrapped around tool execution. When you enable it, things like exec, file reads/writes, and browser automation run inside this contained sandbox instead of directly on your host. That distinction is huge. Without it, anything the agent does, whether instructed by you or maliciously by an attacker, runs as whatever user is running the gateway. On most setups, that’s your own user machine, with full access to their directory, where your API tokens live, and everything else. With the sandbox enabled, that same malicious exec call lands inside a container with no network by default, a constrained filesystem, and no persistent state.

#### Run security audits periodically

OpenClaw offers a built-in audit command (openclaw security audit) that scans your local configuration, filesystem permissions, and channel policies for common misconfigurations. It covers over 50 checks across config, channels, plugins, gateway exposure, browser control, and the exec permission model, without making any changes to your system.

In case an extended scan needs to be done, the --deep flag can be used, which extends the baseline scan with a live gateway probe, browser control exposure checks, and static code-safety analysis of installed plugins and skills. The command will not make any change to the system again.

If we want to apply changes, we can use the flag --fix , which applies automatic remediations for the misconfigurations it finds.

It is recommended to execute it at least daily to see if any changes have happened, which might affect you, or if any configuration is not considered safe anymore. Also, since new vulnerabilities have been and will be found for OpenClaw, it is recommended to scan for them using the audit command.

### The AI that does things (securely)

New technology always introduces new risk. That is not a reason to avoid OpenClaw. It is a reason to run it with your eyes open.

OpenClaw delivers something many of us have wanted for a long time, a capable, autonomous agent that manages the mundane parts of work and lives. That same capability is what makes a compromise serious. The access you grant it is the access an attacker inherits.

This article covered how OpenClaw can be abused, how to detect it, and how to reduce your exposure. No configuration makes it perfectly safe, but the practices outlined here make it meaningfully harder to exploit.
