Back to skill

Security audit

量子密信对话机器人接入openclaw

Security checks for vulnerabilities and agentic risk

Overview

This messaging plugin is purpose-aligned, but it exposes a webhook and sends credentials/messages in ways that need careful review before installation.

Install only after the webhook is protected with authentication or signatures, HTTPS is required for both inbound and outbound traffic, pairing/allowlist checks are enforced before agent dispatch, request size/rate limits are added, and media uploads are restricted to an approved directory or opaque media IDs. Treat existing keys as sensitive because the current defaults can put them in plaintext URLs.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.ts:43
Finding

Unauthenticated Webhook Bypasses Pairing and Allowlist Controls

Content
View full analysis
{ if (req.method === "OPTIONS") { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type"); res.statusCode = 200; res.end(); return; } if (req.url !== account.webhookPath || req.method !== "POST") { res.statusCode = 404; res.end("Not Found"); return; } let body = ""; req.on("data", (chunk: any) => { body += chunk.toString(); }); req.on("end", async () => { try { const payload = JSON.parse(body); await handleIncomingMessage(account, payload, pluginApi); res.statusCode = 200; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify({ success: true })); } catch (error) { console.error("[quantum-im] Webhook error:", error); res.statusCode = 400; res.end(JSON.stringify({ error: "Invalid payload" })); } }); }); ``` The plugin declares direct-message security controls: ```ts security: { dm: { channelKey: "quantum-im", resolvePolicy: (account) => account.dmSecurity, resolveAllowFrom: (account) => account.allowFrom, defaultPolicy: "pairing", }, }, ``` However, the custom webhook directly processes the supplied identity and dispatches the content: ```ts const { type, phone, groupId, callBackUrl, textMsg, imageMsg, fileMsg, news } = payload; const isGroup = Boolean(groupId); const chatType = isGroup ? "group" : "direct"; const peerId = isGroup ? groupId! : phone; ``` ### Technical Analysis The webhook verifies only the request method and URL path. It does not verify a cryptographic signatu ...[truncated 1999 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/config.ts:57
Finding

API Credentials, Messages, and Files Are Transmitted over Plaintext HTTP by Default

Content
View full analysis
{ ``` ### Technical Analysis The runtime default is `http://imtwo.zdxlz.com`. Unless the operator overrides it, outbound text messages and file uploads are transmitted without TLS. The API key is also carried in the URL query string. Under HTTP, the complete path and query are visible to network observers. Even when HTTPS is configured, query parameters can be retained by reverse proxies, access logs, monitoring systems, and application logs. The affected traffic can include: - The reusable Quantum IM API key. - Agent-generated message text. - Uploaded file contents. - File names and metadata. - API responses. ### Attack Path 1. An operator installs the plugin and retains the documented default host. 2. The plugin constructs a URL containing the API key, such as: ```text http://imtwo.zdxlz.com/im-external/v1/webhook/s ...[truncated 833 chars]
Remediation
View remediation
``` 4. Validate the configured URL: - Allow only `https:`. - Reject embedded credentials. - Restrict unexpected ports where practical. - Optionally allowlist approved API hostnames. 5. Use normal TLS certificate and hostname verification; do not introduce an option that disables certificate validation. 6. Ensure errors and logs never include URLs containing credentials. 7. Rotate all API keys that may previously have been transmitted over HTTP. 8. Update `README.md` and `SKILL.md` so every API and webhook example uses HTTPS. 9. Document secure TLS termination requirements for inbound webhooks. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.ts:56
Finding

Unbounded Webhook Request Buffer Enables Remote Denial of Service

Content
View full analysis
{ body += chunk.toString(); }); req.on("end", async () => { try { const payload = JSON.parse(body); await handleIncomingMessage(account, payload, pluginApi); res.statusCode = 200; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify({ success: true })); } catch (error) { console.error("[quantum-im] Webhook error:", error); res.statusCode = 400; res.end(JSON.stringify({ error: "Invalid payload" })); } }); ``` ### Technical Analysis The webhook appends every received chunk to a JavaScript string without enforcing a maximum body size. It does not reject an excessive `Content-Length`, stop reading after a threshold, or destroy oversized requests. The server also does not configure application-specific request timeouts or concurrency controls. An attacker can therefore send very large request bodies or maintain slow, incomplete uploads. Repeated string concatenation and subsequent JSON parsing can significantly increase memory and CPU consumption. ### Attack Path 1. The attacker connects to the exposed webhook endpoint. 2. The attacker sends a POST request with a very large body, or streams data slowly without completing the request. 3. The server continually appends incoming chunks to `body`. 4. Multiple concurrent requests increase retained memory and open-connection usage. 5. If a request completes, `JSON.parse` adds further CPU and memory pressure. 6. The OpenClaw gateway becomes slow, runs out of memory, or terminates. ### Impact Assessment A remote unauthenticated attacker can degrade availability of the plugin and potentially the entire gateway process. The resulting disruption can affect: - Inbound processing for Quantum IM. - Other pl ...[truncated 240 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.ts:221
Finding

Unrestricted Local File Paths Can Be Read and Uploaded as Outbound Media

Content
View full analysis
{ const account = resolveQuantumImAccount(ctx.cfg, ctx.accountId); const api = getOrCreateApi(account); const filePath = ctx.mediaUrl; const isImage = filePath.match(/\.(jpg|jpeg|png|gif|webp)$/i); let result; if (isImage) { result = await api.sendImage(ctx.to, filePath, ctx.metadata?.groupId); } else { result = await api.sendFile(ctx.to, filePath, ctx.metadata?.groupId); } return { channel: "quantum-im", messageId: result.messageId }; }, ``` The upload implementation directly reads the supplied path: ```ts async uploadFile(filePath: string, fileType: 1 | 2): Promise { return new Promise((resolve, reject) => { const url = new URL(`${this.host}/im-external/v1/webhook/upload-attachment?key=${this.key}&type=${fileType}`); console.log(`[quantum-im] upload start type=${fileType} path=${filePath}`); const stat = fs.statSync(filePath); if (stat.size > QuantumImApi.MAX_FILE_SIZE_BYTES) { reject(new Error(`File too large: ${stat.size} bytes (limit: ${QuantumImApi.MAX_FILE_SIZE_BYTES} bytes)`)); return; } const fileContent = fs.readFileSync(filePath); const fileName = filePath.split(/[\\/]/).pop() || "unknown"; ``` ### Technical Analysis The code performs no path canonicalization, approved-directory check, regular-file check, or symbolic-link protection before reading the file. Any readable path passed through `ctx.mediaUrl` is opened under the privileges of the OpenClaw gateway and uploaded to the configured remote API. The 30 MB size check restricts volume but does not protect sensitive files. It is also performed with `statSync`, which follow ...[truncated 1576 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a fuller messaging-channel plugin with conversational and account-management features. The supplied code is much narrower: it is an outbound webhook client for sending messages and uploading attachments. While it does support text, image, and file sending, several headline capabilities in the description are absent from the implementation. In particular, there is no inbound message handling or AI reply logic, no multi-account management layer, no secure pairing flow, and no implemented support for rich-media/news sending despite the type definition containing a news shape. Additionally, although methods accept target and groupId parameters, the request payload sent to the webhook does not include any actual routing identifiers, so explicit group/private chat support is not evidenced by this chunk. Therefore the description overstates and materially misrepresents the code’s implemented behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README instructs users to expose a public webhook endpoint for an external messaging platform but does not clearly warn that inbound messages and related metadata will traverse third-party infrastructure and a publicly reachable server. In a messaging integration, this can lead operators to deploy an Internet-exposed callback without understanding privacy, authentication, logging, and abuse risks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 153)May include surrounding context.

测试 Webhook 接收

bash
curl -X POST http://localhost:3777/quantum-im \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation instructs users to configure both the IM API host and webhook callback over plain HTTP, which exposes message contents, identifiers, and any shared secret/key to interception or modification in transit. For an instant-messaging integration, this context makes the issue more dangerous because private communications and webhook authenticity are central to the plugin's trust model.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 334)May include surrounding context.

测试 Webhook 接收

bash
curl -X POST http://localhost:3777/quantum-im \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 156)May include surrounding context.

测试 Webhook 接收

bash
curl -X POST http://localhost:3777/quantum-im \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The webhook server accepts arbitrary inbound network payloads and forwards message content into the agent runtime, but the code shows no authentication, signature verification, or origin validation for webhook requests. In this context, the issue is more dangerous than a mere disclosure problem because unauthenticated remote parties may be able to inject messages into agent sessions and trigger outbound replies or workflow actions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Natural-language strings such as labels, descriptions, and CLI output are hardcoded in Chinese, which imposes a specific language on users without opt-in. The file does not indicate that the plugin is intentionally region-specific or provide any mechanism for locale selection.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The plugin directly reads ~/.openclaw/openclaw.json from the host HOME directory during registration instead of using the provided plugin API/config flow. This breaks isolation assumptions, can access broader host configuration than intended, and may expose secrets or cause the plugin to act on configuration outside the authorized runtime context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The uploadFile method reads a local file from disk and sends its contents via HTTP(S) to a remote webhook endpoint. Although there are console logs, they are developer-oriented and there is no confirmation prompt, user disclosure comment/docstring, or other user-facing warning that local file data will be transmitted off-system.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The sendRequest method serializes message payloads and transmits them to an external webhook endpoint over HTTP(S). The code logs response details after the fact, but it does not provide a user-facing warning, confirmation, or explanatory comment that message content may be sent to a remote service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The natural-language content of the README appears to require Chinese comprehension throughout, and there is no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking/regional audience. Under the stated policy, forcing a specific language without opt-in is a language/locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The natural-language content in the description and the rest of the markdown is exclusively Chinese, which can effectively force a specific language on users without opt-in. The file does not mention that the skill is region-specific or provide an alternative language option, so it meets the stated locale-policy concern.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This is a manifest file, so vague-trigger checks apply. The manifest declares a channel name but provides no description of how or when the skill should be invoked, nor any constraints or negative examples, leaving activation scope underspecified and potentially broad.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The package description is written in Chinese, and related user-facing metadata elsewhere in the manifest also uses only Chinese labels. For a general-purpose package manifest, this imposes a specific language/locale without indicating user opt-in or a documented region-specific constraint.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
86% confidence
Finding

Using a caret range for a production dependency allows newer minor/patch releases to be installed without explicit review, which can make builds non-reproducible and increase supply-chain risk. In this skill, zod is a runtime dependency, so an unexpectedly vulnerable or compromised release could affect deployed environments.

Content

Scanner excerpt · package.json (reported line 25)May include surrounding context.

json
"node": ">=22"
  },
  "dependencies": {
    "zod": "^3.24.0"
  },
  "devDependencies": {
    "typescript": "^5.0.0",

Unverifiable Dependency: zod has 1 known advisory(ies) (CVE-2023-4316 (Zod denial of service vulnerability)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
83% confidence
Finding

The manifest uses an unpinned zod dependency despite a known advisory history, so consumers cannot verify from this file whether a safe version will be installed. Because zod is a runtime dependency, this uncertainty increases the chance of shipping a vulnerable release if resolution pulls an affected version.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 28)May include surrounding context.

json
"zod": "^3.24.0"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
    "vitest": "^2.0.0"
  },
  "openclaw": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 29)May include surrounding context.

json
},
  "devDependencies": {
    "typescript": "^5.0.0",
    "vitest": "^2.0.0"
  },
  "openclaw": {
    "extensions": ["./index.ts"],

Unverifiable Dependency: vitest has 3 known advisory(ies) (CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed); CVE-2026-84373 (Vitest: Path Traversal / Arbitrary File Read via @vitest/mocker Redirect Mock); CVE-2025-24964 (Vitest allows Remote Code Execution when accessing a malicious website while Vit)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The channel's user-facing label, selection label, docs label, and blurb are all presented only in Chinese. This appears to enforce a specific language for end users without any visible opt-in, fallback, or justification that the skill is limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.