Back to skill

Security audit

OpenClaw Mobile Gateway Installer

Security checks for vulnerabilities and agentic risk

Overview

This installer also runs a broad unauthenticated admin gateway that can expose secrets and change OpenClaw state, so it should be reviewed carefully before installation.

Install only in a tightly controlled environment after reviewing the backend. Do not expose port 4800 to untrusted networks; place it behind authentication, TLS, and firewall rules. Treat any configured OpenClaw, model-provider, and channel credentials as sensitive, and prefer rotating them if this service has already been reachable. Review the install and uninstall scripts because they create an autostarting system service and remove service/config/install directories.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (7)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
backend/src/app.ts:115
Finding
Unauthenticated Administrative API Exposed on All Network Interfaces<![CDATA[ ## Vulnerability Details **File Location**: `backend/src/app.ts:115-118, 139-198, 251-270, 298-317, 512-559`; `backend/src/index.ts:3-7` **Vulnerability Type**: Missing authentication and authorization on a remotely accessible management API **Risk Level**: Critical ### Vulnerable Code ```ts export function createApp() { const app = express(); seedTokenUsage(); app.use(cors()); app.use(express.json({ limit: "2mb" })); app.get("/api/models", (_req, res) => { res.json(listModels()); }); app.put("/api/models", async (req, res, next) => { try { const payload = parseRequest(modelSchema, req.body); const modelId = payload.modelId ?? payload.id; const nextModel = { ...payload, modelId, providerId: payload.providerId ?? payload.platform ?? "openai", platform: payload.platform ?? payload.providerId ?? "openai" }; res.json(await upsertModel(nextModel)); } catch (error) { next(error); } }); app.get("/api/channels", (_req, res) => { res.json(listChannels()); }); app.get("/api/memory/files", async (req, res, next) => { try { const query = parseRequest(memoryQuerySchema, req.query); res.json(await listMemoryFiles(query.agentId, query.category)); } catch (error) { next(error); } }); app.post("/api/services/control", (req, res) => { const payload = parseRequest(gatewayServiceControlSchema, req.body); res.json(controlGatewayService(payload.action)); }); } ``` ```ts const port = Number(process.env.PORT ?? 4800); const app = createApp(); app.listen(port, () => { console.log(`OpenClaw gateway running on http://localhost:${port}`); }); ``` ### Technical Analysis No authentication or authorization middleware is registered before the administrative routes. The `securityConfig.accessPasswordSet` setting is only stored as state and is not enforced by request middleware. Calling `app.listen(port)` without a host ...[truncated 1586 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add mandatory authentication middleware before every `/api/*` route. 2. Use short-lived, securely validated tokens or mutually authenticated TLS rather than a static client-side password. 3. Implement role-based authorization so ordinary mobile clients cannot access credential, memory, log, configuration, or service-control endpoints. 4. Bind to `127.0.0.1` by default: ```ts app.listen(port, "127.0.0.1", () => { console.log(`Gateway listening on 127.0.0.1:${port}`); }); ``` 5. Require an explicitly configured secure deployment mode before binding to a non-loopback interface. 6. Place remote access behind an authenticated TLS reverse proxy and firewall port 4800 from untrusted networks. 7. Replace unrestricted `cors()` with a strict allowlist and reject requests with untrusted `Origin` headers. 8. Add rate limiting, request auditing, authorization tests, and alerts for configuration or service-control operations. 9. Remove application-level `sudo` fallbacks unless a narrowly scoped operational requirement has been documented and reviewed. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
backend/src/services.ts:90
Finding
Model API Keys and Channel Secrets Disclosed in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `backend/src/services.ts:90-115, 193-210, 366-369, 438-443`; `backend/src/app.ts:163-165, 190-192` **Vulnerability Type**: Plaintext secret disclosure through API responses **Risk Level**: Critical ### Vulnerable Code ```ts const providerApiKey = toText(providerObj.apiKey, ""); const providerBaseUrl = toText(providerObj.baseUrl, ""); const providerModels = Array.isArray(providerObj.models) ? providerObj.models : []; for (const item of providerModels) { const modelObj = pickObject(item); const modelId = toText(modelObj.id, ""); if (!modelId) { continue; } const nextModel: ModelConfig = { id: modelId, modelId, providerId, platform, name: toText(modelObj.name, modelId), enabled: providerEnabled && toBool(modelObj.enabled, true), maxTokens: toNumber(modelObj.maxTokens, toNumber(modelObj.contextWindow, 8192)), apiKey: providerApiKey, baseUrl: providerBaseUrl }; result.set(modelId, nextModel); } ``` ```ts const robotSecret = toText( channelObj.appSecret, toText(defaultAccount.appSecret, "") ); result.push({ id, name: toText(channelObj.name, id === "feishu" ? "Feishu channel" : id), enabled: toBool(channelObj.enabled, true), weight: toNumber(channelObj.weight, id === "feishu" ? 200 : 100), robotId, robotSecret }); ``` ```ts app.get("/api/models", (_req, res) => { res.json(listModels()); }); app.get("/api/channels", (_req, res) => { res.json(listChannels()); }); ``` ### Technical Analysis The gateway reads model-provider API keys and channel application secrets from the OpenClaw runtime configuration and places the complete values in `ModelConfig` and `ChannelConfig` objects. The corresponding GET endpoints serialize those objects directly. No masking, response DTO, field omission, or authorization check protects these values. Consequently, possession of network access to the gateway is sufficient to retrieve credentials intended for ...[truncated 833 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never include secret values in model or channel read responses. 2. Define dedicated response types that omit `apiKey`, `robotSecret`, tokens, and authorization-header values. 3. Return only metadata such as: ```json { "apiKeyConfigured": true, "apiKeyHint": "****abcd" } ``` 4. Treat an omitted secret on update as “leave unchanged”; require a separate, privileged rotation operation to replace it. 5. Require elevated authorization and recent re-authentication for secret rotation. 6. Store secrets in an operating-system credential facility or dedicated secret manager instead of general JSON configuration. 7. Rotate all credentials that may already have been exposed through these endpoints. 8. Add automated response-schema tests that fail if secret fields are serialized. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
backend/src/services.ts:235
Finding
Server-Side Request Forgery and Sensitive Header Forwarding Through Mutable Targets<![CDATA[ ## Vulnerability Details **File Location**: `backend/src/app.ts:139-160`; `backend/src/schemas.ts:53-62`; `backend/src/services.ts:235-258, 272-292, 300-354` **Vulnerability Type**: SSRF with arbitrary destination and sensitive data forwarding **Risk Level**: High ### Vulnerable Code ```ts export const openClawTargetUpdateSchema = z.object({ domain: z.string().min(3), apiBaseUrl: z.string().url(), healthPath: z.string().min(1), chatPaths: z.array(z.string().min(1)).min(1), authHeaderName: z.string().optional(), authHeaderValue: z.string().optional(), extraHeaders: z.record(z.string(), z.string()).optional(), timeoutMs: z.number().int().min(500).max(20000).optional() }); ``` ```ts app.put("/api/openclaw/targets", (req, res) => { const payload = parseRequest(openClawTargetUpdateSchema, req.body); const result = updateOpenClawTargetConfig(payload); return res.json(result); }); ``` ```ts const response = await fetch(`${target.apiBaseUrl}${healthPath}`, { method: "GET", headers: { ...authHeaders, ...(target.extraHeaders ?? {}) }, signal: AbortSignal.timeout(target.timeoutMs ?? 5000) }); ``` ```ts const response = await fetch(`${payload.target.apiBaseUrl}${endpoint}`, { method: "POST", headers: { "Content-Type": "application/json", ...(payload.target.gatewayToken ? { Authorization: `Bearer ${payload.target.gatewayToken}` } : {}), ...authHeaders, ...(payload.target.extraHeaders ?? {}) }, body: JSON.stringify({ model: payload.modelId, messages: payload.messages }), signal: AbortSignal.timeout(payload.target.timeoutMs ?? 2500) }); ``` ### Technical Analysis The URL schema verifies only that `apiBaseUrl` has URL syntax. It does not restrict protocols to HTTPS, enforce trusted hostnames, reject loopback or private address ranges, prevent DNS rebinding, or control redirects. A caller can modify an existing target and then cause the server to issue requests through the pro ...[truncated 1443 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require privileged authentication before target configuration can be changed. 2. Maintain an immutable allowlist of approved HTTPS hostnames and ports. 3. Resolve destination hostnames before connecting and reject loopback, link-local, private, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. 4. Repeat address validation after DNS resolution and for every redirect, or disable redirects entirely. 5. Reject non-HTTPS schemes in production. 6. Do not accept arbitrary `extraHeaders` or attacker-selected authentication-header names. 7. Bind each credential to one approved destination and never forward it after a destination change. 8. Use a dedicated outbound proxy with network-level destination restrictions. 9. Limit response sizes and timeouts, and record target configuration and outbound-request audit events. ]]>

T02 · Agent Memory Poisoning

Error
Location
backend/src/app.ts:251
Finding
Unauthenticated Persistent Agent Memory Poisoning<![CDATA[ ## Vulnerability Details **File Location**: `backend/src/app.ts:251-270`; `backend/src/services.ts:631-691` **Vulnerability Type**: Unauthorized persistent Agent memory read, write, and deletion **Risk Level**: High ### Vulnerable Code ```ts app.get("/api/memory/files", async (req, res, next) => { try { const query = parseRequest(memoryQuerySchema, req.query); res.json(await listMemoryFiles(query.agentId, query.category)); } catch (error) { next(error); } }); app.put("/api/memory/files", async (req, res, next) => { try { const payload = parseRequest(memoryUpsertSchema, req.body); res.json(await upsertMemoryFile(payload)); } catch (error) { next(error); } }); app.delete("/api/memory/files", async (req, res, next) => { try { const query = parseRequest(memoryDeleteSchema, req.query); res.json(await deleteMemoryFile(query)); } catch (error) { next(error); } }); ``` ```ts export async function upsertMemoryFile(payload: { agentId: string; category: string; fileName: string; content: string; }): Promise<MemoryFileItem> { const safeAgentId = safeSegment(payload.agentId); const safeCategory = safeSegment(payload.category); const safeFileName = safeSegment(payload.fileName).endsWith(".md") ? safeSegment(payload.fileName) : `${safeSegment(payload.fileName)}.md`; const dir = path.join(memoryDir, safeAgentId, safeCategory); await fs.mkdir(dir, { recursive: true }); const filePath = path.join(dir, safeFileName); await fs.writeFile(filePath, payload.content, "utf-8"); const stat = await fs.stat(filePath); return { agentId: safeAgentId, category: safeCategory, fileName: safeFileName, content: payload.content, updatedAt: stat.mtime.toISOString() }; } ``` ### Technical Analysis The filename components are sanitized, which limits straightforward path traversal, but there is no identity, ownership, authorization, approval, or content-trust boundary. Any rea ...[truncated 1234 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication for all memory operations. 2. Authorize access by Agent, tenant, user, and memory category. 3. Require explicit human approval or a trusted internal workflow for persistent memory writes. 4. Store provenance information, including author identity, source request, timestamp, and content hash. 5. Separate untrusted user content from trusted behavioral instructions. 6. Treat retrieved memory as untrusted data rather than executable instructions. 7. Add version history, rollback support, integrity checks, and immutable audit records. 8. Prevent arbitrary clients from selecting another Agent's identifier. 9. Encrypt sensitive memory at rest and redact it from ordinary API responses. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
backend/src/services.ts:993
Finding
Path Traversal in Markdown File Update Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `backend/src/schemas.ts:48-51`; `backend/src/app.ts:443-452`; `backend/src/services.ts:993-997` **Vulnerability Type**: Directory traversal and arbitrary Markdown file overwrite **Risk Level**: High ### Vulnerable Code ```ts export const markdownUpdateSchema = z.object({ fileName: z.string().endsWith(".md"), content: z.string() }); ``` ```ts app.put("/api/md-files", async (req, res, next) => { try { const payload = parseRequest(markdownUpdateSchema, req.body); const result = await updateMarkdownFile(payload.fileName, payload.content); res.json(result); } catch (error) { next(error); } }); ``` ```ts export async function updateMarkdownFile( fileName: string, content: string ): Promise<MarkdownFileRecord> { await fs.mkdir(markdownDir, { recursive: true }); await fs.writeFile(path.join(markdownDir, fileName), content, "utf-8"); return { fileName, content }; } ``` ### Technical Analysis Validation requires only that the supplied string end in `.md`. It does not reject absolute paths, path separators, or `..` components. `path.join(markdownDir, fileName)` normalizes traversal components and can produce a path outside `markdownDir`. The endpoint is also unauthenticated. A remote client can therefore overwrite any `.md` file reachable with the service account's filesystem permissions, provided that parent directories exist or are otherwise writable. ### Attack Path 1. The attacker determines or guesses the relative location of a writable Markdown file. 2. The attacker sends a PUT request to `/api/md-files`. 3. The request uses a filename such as `../../skills/example/SKILL.md`. 4. The schema accepts the value because it ends in `.md`. 5. `path.join` resolves the traversal outside the intended Markdown directory. 6. `fs.writeFile` replaces or creates the selected Markdown file with attacker-controlled content. 7. If the overwritten file is later loaded as an instruction, S ...[truncated 479 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Accept only a strict basename, for example: ```ts if (fileName !== path.basename(fileName) || !/^[A-Za-z0-9._-]+\.md$/.test(fileName)) { throw new Error("Invalid Markdown filename"); } ``` 2. Resolve and verify the final path: ```ts const root = path.resolve(markdownDir); const destination = path.resolve(root, fileName); if (!destination.startsWith(`${root}${path.sep}`)) { throw new Error("Path escapes Markdown directory"); } ``` 3. Reject absolute paths, both slash types, NUL characters, and `..` components. 4. Use `lstat` and safe file-open flags where necessary to prevent symlink-based escapes. 5. Require authentication and file-level authorization. 6. Restrict writable files to a predefined allowlist and maintain versioned backups. 7. Run the service with filesystem permissions that prevent modification of code, Skill definitions, and system configuration. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
install.sh:46
Finding
Upstream Authentication Token Stored in a Potentially World-Readable Environment File<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:46-56` **Vulnerability Type**: Insecure plaintext secret-file permissions **Risk Level**: Medium ### Vulnerable Code ```bash sudo mkdir -p /etc/openclaw-mobile-gateway sudo tee /etc/openclaw-mobile-gateway/env >/dev/null <<EOF OPENCLAW_API_BASE_URL=${OPENCLAW_API_BASE_URL} OPENCLAW_AUTH_HEADER_NAME=${OPENCLAW_AUTH_HEADER_NAME} OPENCLAW_AUTH_HEADER_VALUE=${OPENCLAW_AUTH_HEADER_VALUE} OPENCLAW_CONFIG_PATH=${OPENCLAW_CONFIG_PATH} OPENCLAW_RUNTIME_CONFIG_PATH=${OPENCLAW_RUNTIME_CONFIG_PATH} OPENCLAW_USAGE_CONFIG_PATH=${OPENCLAW_USAGE_CONFIG_PATH} OPENCLAW_USAGE_DAYS=${OPENCLAW_USAGE_DAYS} PORT=${GATEWAY_PORT} NODE_ENV=production EOF ``` ### Technical Analysis The installer writes the upstream authorization value in plaintext to `/etc/openclaw-mobile-gateway/env` but never explicitly configures file ownership or permissions. File creation through `sudo tee` is subject to the effective process umask. Under a common `022` umask, the resulting file can be mode `0644`, making it readable by every local user. The file is referenced by systemd as an `EnvironmentFile`, but systemd does not require it to be globally readable. ### Attack Path 1. The installer creates `/etc/openclaw-mobile-gateway/env`. 2. The file receives default permissions that allow local users to read it. 3. An unprivileged local user reads the file. 4. The user extracts `OPENCLAW_AUTH_HEADER_VALUE`. 5. The user reuses the bearer token against the configured upstream OpenClaw API. ### Impact Assessment Any local user able to read the environment file can obtain the upstream authorization credential. The resulting access is determined by the token's scope and may include model usage, administrative API access, data retrieval, or financial impact through unauthorized consumption. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the directory and file with explicit restrictive permissions: ```bash sudo install -d -m 750 -o root -g "${RUN_GROUP}" /etc/openclaw-mobile-gateway sudo install -m 640 -o root -g "${RUN_GROUP}" /dev/null /etc/openclaw-mobile-gateway/env ``` 2. If only root must read the file, use mode `0600`. 3. Write to a securely created temporary file and atomically install it with the required mode. 4. Avoid exposing secrets in process arguments or command output. 5. Prefer systemd credentials, an operating-system keyring, or a dedicated secret manager. 6. Validate and safely encode environment-file values containing newlines or special characters. 7. Rotate existing tokens after correcting permissions. 8. Add an installation check that fails if the file is readable by unintended users. ]]>

T08 · Insecure Dependencies

Warning
Location
install.sh:42
Finding
Unpinned and Non-Reproducible Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:42-44`; `backend/package.json:12-27` **Vulnerability Type**: Unsafe dependency resolution and unnecessary development dependencies in production **Risk Level**: Medium ### Vulnerable Code ```bash pushd "${INSTALL_DIR}/apps/backend" >/dev/null npm install --omit=optional popd >/dev/null ``` ```json { "dependencies": { "cors": "^2.8.5", "express": "^4.19.2", "zod": "^3.23.8" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/jest": "^29.5.12", "@types/node": "^20.14.12", "@types/supertest": "^6.0.2", "jest": "^29.7.0", "supertest": "^7.0.0", "ts-jest": "^29.1.5", "tsx": "^4.16.2", "typescript": "^5.5.4" } } ``` ### Technical Analysis The project does not include a lockfile, uses caret version ranges, and runs `npm install` during system installation. This allows dependency versions to change between otherwise identical installations. NPM lifecycle scripts are not disabled, so scripts supplied by resolved packages can execute under the selected service user's account. `--omit=optional` does not omit development dependencies. The production systemd unit directly starts `tsx` from `node_modules`, making a development tool part of the production execution chain and expanding the dependency attack surface. No evidence shows that a currently declared package is malicious. The confirmed issue is the unsafe and non-reproducible installation process, which increases exposure to future package compromise or registry manipulation. ### Attack Path 1. A dependency account, transitive package, or configured NPM registry is compromised, or a permitted version range resolves to a malicious release. 2. A user runs `install.sh`. 3. `npm install` resolves the current package graph rather than a reviewed locked graph. 4. A malicious package lifecycle script executes during installation, or malicious package code is ...[truncated 608 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate, review, and commit `package-lock.json`. 2. Replace `npm install` with a reproducible installation command such as: ```bash npm ci --omit=dev --ignore-scripts ``` Enable required scripts only after reviewing and explicitly allowlisting them. 3. Build TypeScript during a trusted packaging or build stage and run compiled JavaScript in production. 4. Move production-required packages to `dependencies`; do not execute the service through `tsx`. 5. Pin critical packages and regularly review transitive dependency changes. 6. Configure a trusted registry explicitly and validate lockfile integrity metadata. 7. Run vulnerability, provenance, and license checks in CI. 8. Package reviewed build artifacts so deployment does not dynamically resolve dependencies from the network. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (74)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description suggests a narrowly scoped skill for one-command deployment and lifecycle management of the OpenClaw mobile gateway as a system service. The code does include some related capabilities, such as service status/control, gateway restart, OpenClaw update, uninstall, logs, and target probing. However, its primary behavior is much broader: it exposes a comprehensive administrative backend API covering chat operations, assistant sessions, OpenClaw target resolution, CRUD for models/skills/channels/agents, memory and markdown file management, cron scheduling, websocket messaging, routing, heal workflows, security/settings, and usage statistics. These are materially undeclared capabilities and indicate the skill is not just a service installer/manager but a full admin/control plane backend.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description says this skill installs and manages OpenClaw as a system service and supports lifecycle actions like deploy, start, stop, upgrade, and uninstall. The provided code does not implement any of those behaviors. It simply initializes the app and starts listening on a port, which is consistent with running a web server but not with system service management or installation. This is a material mismatch in primary purpose and capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The supplied code does not implement installation or service-management logic for OpenClaw. Instead, it provides input-validation schemas for a broad backend application. Although a small subset references gateway service control and logs, the overall code chunk’s primary behavior is schema definition for many unrelated backend features, not one-command deploy/start/stop/upgrade/uninstall of a system service. This is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description suggests a narrowly scoped skill for one-command deployment and service lifecycle management of the OpenClaw mobile gateway. While the code does include some related pieces—checking systemd service status, starting/stopping/restarting the `openclaw-mobile-gateway` service, reading logs, and a mock uninstall/update timestamp—it is not primarily an installer/service-manager implementation. There is no real deployment flow, no actual install routine for the service, and uninstall/upgrade behavior is mostly simulated or limited to state/config updates. Instead, most of the code implements a comprehensive backend/admin API for OpenClaw: configuration management, skill/model/channel/agent CRUD, chat proxying, token accounting, markdown/memory file storage, routing/healing, websocket sessions, and mobile app update policy. These are materially broader and different capabilities than the declared purpose, so this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill installs and manages the OpenClaw mobile gateway as a system service. However, the supplied code chunk is a TypeScript store/config module exporting static configuration objects and arrays plus a small seed function for token usage records. There are no commands, process control, service unit operations, package installation steps, upgrade/uninstall routines, or trigger handling for gateway lifecycle management. Its primary purpose is backend configuration/state definition for models, channels, routing strategies, heal policies, app updates, security, agents, and communication behavior, which is materially different from the declared operational service-management purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description presents an operational system-service management skill for OpenClaw gateway deployment and lifecycle actions. However, the supplied code is purely a type definition file for many backend application entities. While a few interfaces mention gateway/service status, there is no executable logic for managing a system service. The primary purpose of this code chunk is schema/type modeling for a backend platform, not gateway installation or service control. This is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared purpose is system-service lifecycle management for OpenClaw, but the supplied code chunk does not perform any of those actions. It merely creates IDs using a prefix, timestamp, and random string. This is a materially different primary purpose and appears unrelated to the described skill behavior, so it should be flagged as a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents this skill as a one-command installer and manager for the OpenClaw mobile gateway system service. However, the provided code only checks the current status of an existing service, verifies a listening port, and calls local health/API endpoints. That is a monitoring/verification script, not an installation or management implementation. While checking status can support service management, it does not match the primary declared purpose of deploy/start/stop/upgrade/uninstall, so this is a material description-behavior mismatch.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This file exposes a very broad administrative API surface that goes far beyond the declared purpose of installing and managing the OpenClaw mobile gateway service. In a skill context, that scope expansion is dangerous because it enables unrelated data management, messaging, configuration changes, and system actions that increase attack surface and violate least privilege.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
Chat and assistant messaging endpoints are unrelated to a gateway installer/service-management skill and create an unjustified capability to send content to backend targets. That broadens the blast radius from service administration into message proxying and remote interaction, which could be abused for unauthorized data exchange or lateral operations.

Missing User Warnings

High
Confidence
94% confidence
Finding
The gateway restart endpoint triggers a system-level action immediately with no visible confirmation or safety gate in this file. That makes accidental invocation or abuse capable of causing service disruption and denial of service for users depending on the gateway.

Missing User Warnings

High
Confidence
93% confidence
Finding
The system update endpoint applies an update action directly from request input without any visible warning, approval step, or compatibility safeguards in this file. Uncontrolled update execution can lead to unexpected code changes, outages, or rollback difficulties if triggered accidentally or by an unauthorized caller.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This module substantially exceeds the declared scope of a gateway installer/manager by implementing chat proxying, content management, routing, telemetry, updates, and configuration mutation. That mismatch increases attack surface and creates capability creep: a user invoking an installer skill could unintentionally grant a broad administrative control plane over models, channels, secrets, files, and runtime behavior.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The code sends arbitrary user/assistant messages and credentials to configurable remote endpoints via fetch, effectively acting as a chat proxy unrelated to gateway installation. In the context of an installer skill, this is dangerous because it can exfiltrate prompts, secrets, and operational metadata to attacker-controlled targets under the guise of service management.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
sudo systemctl stop "${SERVICE_NAME}" 2>/dev/null || true
sudo systemctl disable "${SERVICE_NAME}" 2>/dev/null || true
sudo rm -f "/etc/systemd/system/${SERVICE_NAME}.service"
sudo systemctl daemon-reload
sudo rm -rf /etc/openclaw-mobile-gateway
sudo rm -rf "${INSTALL_DIR}"
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
sudo systemctl disable "${SERVICE_NAME}" 2>/dev/null || true
sudo rm -f "/etc/systemd/system/${SERVICE_NAME}.service"
sudo systemctl daemon-reload
sudo rm -rf /etc/openclaw-mobile-gateway
sudo rm -rf "${INSTALL_DIR}"

echo "Uninstalled ${SERVICE_NAME}."
Confidence
100% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
sudo systemctl disable "${SERVICE_NAME}" 2>/dev/null || true
sudo rm -f "/etc/systemd/system/${SERVICE_NAME}.service"
sudo systemctl daemon-reload
sudo rm -rf /etc/openclaw-mobile-gateway
sudo rm -rf "${INSTALL_DIR}"

echo "Uninstalled ${SERVICE_NAME}."
Confidence
100% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README instructs operators to export a bearer token into their shell environment and immediately execute an installation script that performs system changes, but provides no warning about secret exposure, privilege requirements, or review of the script before execution. In practice, environment variables can be exposed through shell history, process inspection, logs, or inherited subprocesses, and combining secret handling with one-command install increases the chance of accidental credential leakage or unsafe deployment.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The uninstall command is presented as a simple one-liner with no notice that it may stop services, remove files, or alter system configuration. This creates a real risk of accidental destructive action by users who may not understand the operational impact or whether the removal is reversible.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill advertises shell, environment-variable, and network-driven installation behavior but does not declare any explicit tool scope or permissions. For an installer that can modify system services and consume secrets from environment variables, missing scope boundaries increases the risk of over-broad execution and weak user consent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill describes one-command installation, service registration, auto-start, and uninstall, but does not clearly warn that it will make persistent system-level changes and that uninstall may be destructive. In an agent context, weak disclosure can lead users to approve privileged actions without understanding service, filesystem, or startup impacts.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation tells users to export a bearer token in an environment variable without any warning about secret handling, shell history, process exposure, or log leakage. Because this is an installer skill that may call shell commands and system services, poor token-handling guidance can expose credentials to other users, scripts, or telemetry.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The file manages agents, memory files, cron jobs, websocket chat sessions, and assistant sessions—objects unrelated to installing or controlling the gateway service. Combining these capabilities in one skill violates separation of duties and gives the skill unnecessary authority over application state and automation.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The uninstall endpoint performs a destructive action immediately and this file shows no confirmation, warning, or safety interlock before removal. In a one-command administrative surface, that increases the risk of accidental or unauthorized service removal with operational impact.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The markdown update endpoint writes user-supplied content to files, yet this file provides no indication of user disclosure, path restriction details, or review workflow. In an admin backend, file-writing primitives are risky because they can modify application content or potentially enable stored content injection depending on how the files are later rendered or used.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
backend/src/services.ts:1150

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
backend/src/services.ts:16

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
backend/src/services.ts:412