Back to skill

Security audit

OpenClaw Agent Compute

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-aligned, but it exposes powerful remote compute and deletion capabilities with weak installation and transport safeguards that users should review before installing.

Install only if you trust the configured Compute Gateway and can issue a narrowly scoped, revocable API key. Use HTTPS-only gateway URLs, avoid the draft Docker starter kit in production until the image is pinned and verified, and require human confirmation or gateway-side policy for command execution, artifact deletion, and session destruction.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/client.js:11
Finding
Compute Gateway Bearer Token Can Be Transmitted over Plaintext HTTP## Vulnerability Details **File Location**: `scripts/client.js:11-28` **Vulnerability Type**: Missing HTTPS protocol enforcement **Risk Level**: Medium ```js const baseUrl = process.env.MCP_COMPUTE_URL; const apiKey = process.env.MCP_COMPUTE_API_KEY; function assertEnv() { if (!baseUrl) throw new Error('Missing MCP_COMPUTE_URL'); if (!apiKey) throw new Error('Missing MCP_COMPUTE_API_KEY'); } async function post(path, body) { assertEnv(); const url = new URL(path, baseUrl); const res = await request(url, { method: 'POST', headers: { 'content-type': 'application/json', 'authorization': `Bearer ${apiKey}` }, body: JSON.stringify(body ?? {}) }); ``` The same unrestricted URL construction and bearer-token transmission pattern is also used by the PUT, GET, and DELETE helpers at `scripts/client.js:38-110`. ### Technical Analysis The documentation states that the private compute gateway is contacted over HTTPS, but `assertEnv()` only verifies that `MCP_COMPUTE_URL` and `MCP_COMPUTE_API_KEY` are present. It does not require the parsed URL to use the `https:` protocol. If `MCP_COMPUTE_URL` is configured with an `http://` URL, the client sends the bearer token and request contents without transport encryption. Sensitive contents can include command strings, command environment values, session information, and uploaded or downloaded artifacts. ### Attack Path 1. A user, deployment script, compromised configuration source, or social-engineering instruction supplies an `MCP_COMPUTE_URL` beginning with `http://`. 2. `assertEnv()` accepts the value because it only checks whether it is non-empty. 3. The client creates requests to the plaintext endpoint and includes `Authorization: Bearer ${apiKey}`. 4. An attacker with a network position between the client and gateway intercepts the bearer token and sensitive request or response data. 5. The attacker reuses the token ...[truncated 455 chars]
Remediation
## Remediation Suggestions - Parse and validate the base URL once during initialization. - Reject every protocol other than `https:`. - If plaintext HTTP is necessary for local development, require an explicit opt-in flag and restrict its use to loopback addresses such as `127.0.0.1` or `::1`. - Reject URLs containing embedded credentials. - Add tests confirming that `http://`, malformed URLs, and unsupported protocols are rejected before any request is made. - Preserve normal TLS certificate verification and document that disabling certificate validation is unsupported. Example hardening: ```js function getValidatedBaseUrl() { if (!baseUrl) throw new Error('Missing MCP_COMPUTE_URL'); if (!apiKey) throw new Error('Missing MCP_COMPUTE_API_KEY'); const parsed = new URL(baseUrl); if (parsed.protocol !== 'https:') { throw new Error('MCP_COMPUTE_URL must use HTTPS'); } if (parsed.username || parsed.password) { throw new Error('MCP_COMPUTE_URL must not contain embedded credentials'); } return parsed; } ```

T08 · Insecure Dependencies

Note
Location
package.json:11
Finding
Dependency Installation Is Not Reproducible or Fully Pinned## Vulnerability Details **File Location**: `package.json:11-13` **Vulnerability Type**: Mutable third-party dependency resolution **Risk Level**: Low ```json "dependencies": { "dotenv": "^16.4.5", "undici": "^6.21.0" } ``` The repository contains no package lockfile, while `README.md:37-40` and `SKILL.md:38-42` instruct users to run: ```bash npm i npm run lint npm run example:exec ``` ### Technical Analysis The caret version ranges permit npm to resolve newer compatible releases than those available when the project was audited. Without a committed `package-lock.json`, transitive dependency versions and integrity hashes are also not fixed. As a result, two installations from the same source tree can install different dependency graphs. Newly published or compromised dependency versions would not have been represented in this audit. npm package lifecycle scripts may also execute during installation if introduced by a dependency. This finding does not establish that the currently declared packages are malicious. The risk arises from mutable, unaudited dependency resolution. ### Attack Path 1. A permitted direct or transitive dependency release is compromised or introduces unsafe behavior. 2. A user follows the documented `npm i` installation instruction. 3. npm resolves the mutable version range and installs a dependency graph newer than the reviewed graph. 4. Malicious code executes through an installation lifecycle script or when the package is imported at runtime. 5. Runtime dependency code may access the process environment, including the compute API key, and make network requests under the user's privileges. ### Impact Assessment Exploitation through a compromised dependency could execute code with the privileges of the user running npm or Node.js. It could access project files, environment variables, and the compute gateway credential. With that credential, an attacker could invoke the com ...[truncated 118 chars]
Remediation
## Remediation Suggestions - Generate, review, and commit a `package-lock.json`. - Use `npm ci` in documentation and automated environments to install the locked dependency graph. - Pin direct dependencies to reviewed versions where operationally practical. - Review dependency updates before merging them and use automated vulnerability monitoring. - Run `npm audit` or an equivalent software composition analysis tool in CI. - Consider installation with lifecycle scripts disabled when they are not required: ```bash npm ci --ignore-scripts ``` - Protect the compute API key with least-privilege gateway permissions and avoid exposing it during build or dependency-installation stages.

T08 · Insecure Dependencies

Warning
Location
starter-kit/docker-compose.yml:1
Finding
Starter Kit Executes an Unverified Mutable Container Image## Vulnerability Details **File Location**: `starter-kit/docker-compose.yml:1-10` **Vulnerability Type**: Mutable container-image dependency **Risk Level**: Medium ```yaml services: openclaw: # NOTE: OpenClaw image name/tag may change. Keep it overrideable. image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest} restart: unless-stopped env_file: - .env volumes: - ./openclaw.config.yml:/app/openclaw.config.yml:ro command: ["--config", "/app/openclaw.config.yml"] ``` The associated quickstart at `starter-kit/README.md:7-12` instructs users to start this configuration: ```bash cp .env.example .env # edit .env with MCP_COMPUTE_URL + MCP_COMPUTE_API_KEY # (optional) set OPENCLAW_IMAGE if the default doesn't exist / isn't public yet docker compose up ``` ### Technical Analysis The default image uses the mutable `latest` tag rather than an immutable digest. The repository also states that the official image and startup behavior remain to be confirmed. Consequently, the actual code executed by `docker compose up` can change after this source package has been reviewed. The container receives the `.env` file containing `MCP_COMPUTE_URL` and `MCP_COMPUTE_API_KEY`. Any code supplied through the mutable image can therefore read those values. The `restart: unless-stopped` policy also causes the selected image workload to restart persistently until explicitly stopped. This finding does not establish that the current registry image is malicious. It identifies an unsafe supply-chain trust boundary in the documented starter-kit workflow. ### Attack Path 1. The registry account, image build pipeline, or mutable `latest` tag is compromised or updated with unsafe code. 2. A user follows the documented starter-kit instructions and runs `docker compose up`. 3. Docker retrieves and starts image content that was not represented in this audit. 4. The container reads `MCP_COMPU ...[truncated 778 chars]
Remediation
## Remediation Suggestions - Confirm the official OpenClaw image source before recommending the starter kit for production use. - Pin the image by immutable digest rather than a mutable tag: ```yaml image: ghcr.io/openclaw/openclaw@sha256:REVIEWED_IMAGE_DIGEST ``` - Establish a documented process for reviewing and updating the pinned digest. - Verify image signatures or provenance attestations in CI or deployment policy. - Scan the image for known vulnerabilities before release. - Use a narrowly scoped, revocable compute API key dedicated to this deployment. - Apply container hardening where compatible, including a non-root user, a read-only root filesystem, dropped Linux capabilities, `no-new-privileges`, and restricted outbound networking. - Replace `restart: unless-stopped` with a policy appropriate to the deployment's trust and availability requirements.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
- `GET /v1/artifacts/{session_id}` (list)
  - `PUT /v1/artifacts/{session_id}/{path}` (upload bytes; `{path}` must be URL-encoded and may include slashes)
  - `GET /v1/artifacts/{session_id}/{path}` (download bytes; `{path}` must be URL-encoded)
  - `DELETE /v1/artifacts/{session_id}/{path}` (delete; `{path}` must be URL-encoded)
- `DELETE /v1/sessions/{session_id}` (destroy)

## Scripts
Confidence
84% confidence
Finding
The skill documents a delete endpoint that accepts a user-controlled path, including encoded slashes, for artifact removal. Without strong server-side path validation and authorization, such parameters are prone to abuse for deleting unintended artifacts, traversing logical namespaces, or tricking an agent into destructive actions against valuable remote session data.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
- `PUT /v1/artifacts/{session_id}/{path}` (upload bytes; `{path}` must be URL-encoded and may include slashes)
  - `GET /v1/artifacts/{session_id}/{path}` (download bytes; `{path}` must be URL-encoded)
  - `DELETE /v1/artifacts/{session_id}/{path}` (delete; `{path}` must be URL-encoded)
- `DELETE /v1/sessions/{session_id}` (destroy)

## Scripts
Confidence
86% confidence
Finding
The documented session-destroy endpoint is an inherently destructive capability and can be abused if exposed to agents without confirmation, least-privilege controls, or ownership checks. In this context, the skill is a public-facing client to a private compute gateway, so accidental or malicious invocation could terminate active jobs, erase transient state, and disrupt users relying on those sessions.

Credential Access

High
Category
Privilege Escalation
Content
## Quickstart

```bash
cp .env.example .env
# edit .env with MCP_COMPUTE_URL + MCP_COMPUTE_API_KEY
# (optional) set OPENCLAW_IMAGE if the default doesn't exist / isn't public yet
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Quickstart

```bash
cp .env.example .env
# edit .env with MCP_COMPUTE_URL + MCP_COMPUTE_API_KEY
# (optional) set OPENCLAW_IMAGE if the default doesn't exist / isn't public yet
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./openclaw.config.yml:/app/openclaw.config.yml:ro
    command: ["--config", "/app/openclaw.config.yml"]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./openclaw.config.yml:/app/openclaw.config.yml:ro
    command: ["--config", "/app/openclaw.config.yml"]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./openclaw.config.yml:/app/openclaw.config.yml:ro
    command: ["--config", "/app/openclaw.config.yml"]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./openclaw.config.yml:/app/openclaw.config.yml:ro
    command: ["--config", "/app/openclaw.config.yml"]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./openclaw.config.yml:/app/openclaw.config.yml:ro
    command: ["--config", "/app/openclaw.config.yml"]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README explicitly states that the skill sends requests to a private Compute Gateway over HTTPS using a bearer token, but it does not clearly warn users that prompts, inputs, and possibly sensitive data may be transmitted to an external service. In an agent-skill context, this omission can lead to unintended disclosure of confidential data because operators may assume the skill runs locally or only within the agent environment.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README advertises artifact list/upload/download/delete capabilities without warning that these operations can modify or remove remote data. In a tool-execution environment, undocumented destructive capability increases the risk of accidental data loss or unsafe delegation because users may invoke the skill without understanding its write/delete effects.

Lp3

Medium
Category
MCP Least Privilege
Confidence
80% confidence
Finding
The skill declares environment-variable requirements and exposes remote compute functionality, but does not specify any explicit tool scope or permissions boundaries. In an agent ecosystem, missing scope declarations can cause the skill to be granted broader access than intended or make risk review harder, especially since the skill can trigger remote command execution through a private gateway.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The documentation advertises session creation, command execution, artifact upload/download, deletion, and session destruction, but provides no user-facing warning that these actions are state-changing and potentially destructive. This increases the chance that an agent or operator invokes dangerous operations without understanding they can delete artifacts, terminate sessions, or run arbitrary commands on remote compute resources.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"lint": "node -c scripts/client.js && node -c scripts/example_exec.js"
  },
  "dependencies": {
    "dotenv": "^16.4.5",
    "undici": "^6.21.0"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "dotenv": "^16.4.5",
    "undici": "^6.21.0"
  }
}
Confidence
71% confidence
Finding
The skill is a public HTTP client that talks to a private Compute Gateway, so leaving undici unpinned can allow unintended upgrades to newer minor/patch releases with security regressions or behavior changes in a network-critical component. Because HTTP parsing, redirects, connection reuse, and header handling are security-sensitive, a floating range increases real supply-chain and transport-layer risk in this context.

Unverifiable Dependency: undici has 16 known advisory(ies) (CVE-2026-1525 (Undici has an HTTP Request/Response Smuggling issue); CVE-2026-6733 (undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse); CVE-2024-24758 (Undici proxy-authorization header not cleared on cross-origin redirect in fetch) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding
The manifest declares undici without an exact version while the package family has multiple published advisories, including issues involving request/response smuggling, response queue poisoning, and redirect/header handling. In a skill that exposes public HTTP-triggered compute functionality and relies on HTTPS communication with a private backend, uncertainty about the actual installed undici version creates meaningful risk because vulnerable client behavior could affect request integrity, header confidentiality, or connection safety.

Static analysis

No suspicious patterns detected.