Back to skill

Security audit

openclaw-hxa-connect

Security checks for vulnerabilities and agentic risk

Overview

The plugin has a coherent messaging purpose, but it should be reviewed because its webhook fallback can accept unauthenticated inbound commands and it exposes powerful HXA administration actions.

Review before installing. Use a least-privilege HXA token, require HTTPS hub URLs, configure webhookSecret and allowlists before exposing the webhook route, avoid granting admin-capable tokens to routine messaging bots, and update the WebSocket dependency if the reported advisory applies.

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 (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.ts:1069
Finding
Unauthenticated Webhooks Are Forwarded as Authorized Agent Commands<![CDATA[ ## Vulnerability Details **File Location**: `index.ts:1069-1078`, with related authorization behavior at `index.ts:845-872` and route registration at `index.ts:1734-1745` **Vulnerability Type**: Authentication bypass and improper authorization **Risk Level**: High ### Vulnerable Code Authentication is performed only when a webhook secret has been configured: ```ts // Verify webhook secret if configured if (acct?.webhookSecret) { const authHeader = req.headers?.authorization ?? ""; const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : ""; if (token !== acct.webhookSecret) { res.writeHead(401, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Unauthorized" })); return; } } ``` Inbound content is subsequently forwarded to the agent and explicitly marked as command-authorized: ```ts const ctxPayload = core.channel.reply.finalizeInboundContext({ Body: formattedBody, BodyForAgent: content, RawBody: content, CommandBody: content, From: from, To: to, SessionKey: route.sessionKey, AccountId: accountId, ChatType: chatType, GroupSubject: chatType === "group" ? (groupSubject || replyTarget) : undefined, SenderName: senderName, SenderId: senderId, Provider: "hxa-connect" as const, Surface: "hxa-connect" as const, MessageSid: messageId || `hxa-connect-${Date.now()}`, Timestamp: Date.now(), WasMentioned: true, CommandAuthorized: true, OriginatingChannel: "hxa-connect" as const, OriginatingTo: to, ConversationLabel: chatType === "group" ? (groupSubject || senderName) : senderName, ...(params.replyToMessageId ? { ReplyToId: params.replyToMessageId } : {}), ...(params.replyToBody ? { ReplyToBody: params.replyToBody } : {}), ...(params.replyToSender ? { ReplyToSender: params.replyToSender } : {}), }); ``` The webhook route is registered regardless of whether a secret exists: ```ts for (const [id, acct] of Object.entries(accounts)) { const webhookPath = a ...[truncated 4028 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Fail closed when no webhook secret is configured** - Do not register the webhook route unless a strong secret or signature-verification key is present. - Alternatively, return a configuration error and refuse all webhook requests until authentication is configured. 2. **Do not unconditionally authorize inbound commands** - Set `CommandAuthorized` only after transport authentication and sender authorization succeed. - Unauthenticated or merely informational events must not be assigned command privileges. 3. **Use robust request authentication** - Prefer an HMAC signature over the raw request body, timestamp, HTTP method, and path. - Compare signatures or bearer secrets using a timing-safe comparison. - Reject stale timestamps and previously used event identifiers to prevent replay attacks. 4. **Adopt restrictive defaults** - Default `dmPolicy` and `groupPolicy` to `allowlist` or disabled. - Require operators to explicitly opt into open access. - Update `SKILL.md` examples to include a webhook secret and secure allowlist policies. 5. **Harden the HTTP boundary** - Apply request body size limits. - Validate the payload against a strict schema. - Reject unknown event types and malformed sender or channel identifiers. - Rate-limit requests and record authentication failures without logging secrets. 6. **Separate messaging and administrative privileges** - Do not make administrative HXA operations available to sessions initiated by untrusted messaging channels. - Require explicit confirmation or a separate privileged tool for role changes, ticket creation, secret rotation, and configuration writes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.ts:254
Finding
Bearer Tokens Can Be Transmitted to Plaintext or Unrestricted Hub URLs<![CDATA[ ## Vulnerability Details **File Location**: `index.ts:254-270`, with related WebSocket SDK configuration at `index.ts:469-480` **Vulnerability Type**: Plaintext sensitive-data transmission and insufficient destination validation **Risk Level**: Medium ### Vulnerable Code The URL check accepts any value beginning with the characters `http`, including plaintext HTTP: ```ts /** Make an authenticated request to the HXA-Connect API with rate-limit retry. */ async function hubFetch( acct: HxaAccountConfig, path: string, init: RequestInit, ): Promise<Response> { if (!acct.hubUrl || !acct.hubUrl.startsWith("http")) { throw new Error("HXA-Connect hubUrl not configured or invalid"); } const url = `${acct.hubUrl.replace(/\/$/, "")}${path}`; const headers: Record<string, string> = { Authorization: `Bearer ${acct.agentToken}`, ...((init.headers as Record<string, string>) ?? {}), }; if (acct.orgId) { headers["X-Org-Id"] = acct.orgId; } if (init.body) { headers["Content-Type"] = "application/json"; } for (let attempt = 0; attempt <= MAX_SEND_RETRIES; attempt++) { const resp = await fetch(url, { ...init, headers }); ``` The same unrestricted URL is supplied to the WebSocket SDK together with the token: ```ts const client = new HxaConnectClient({ url: acct.hubUrl, token: acct.agentToken, orgId: acct.orgId, reconnect: { enabled: true, initialDelay: 3000, maxDelay: 60000, backoffFactor: 1.5, }, }); ``` ### Technical Analysis The plugin's declared messaging function requires network transmission of messages and an authentication token to the configured HXA-Connect hub. That transmission is necessary. However, the implementation does not enforce a secure transport or a trusted destination. The validation condition uses `startsWith("http")` instead of parsing the URL and checking its protocol. It therefore accepts at least: - `http://...`, which sends credentials and content without trans ...[truncated 2207 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Parse and validate URLs structurally** - Use `new URL(acct.hubUrl)` and reject parsing failures. - Require the REST endpoint protocol to be exactly `https:`. - Ensure the SDK connection resolves only to secure HTTPS/WSS transport. - Reject embedded usernames, passwords, fragments, and unsupported schemes. 2. **Restrict plaintext development access** - If local HTTP support is required, permit it only through an explicit development option. - Limit that exception to loopback hosts such as `127.0.0.1`, `::1`, or `localhost`. - Display a prominent warning and prevent the exception in production mode. 3. **Constrain credential destinations** - Support an administrator-defined hostname allowlist. - Revalidate the destination after redirects and prohibit forwarding Authorization headers to a different origin. - Consider disabling redirects for authenticated requests unless each redirect is explicitly validated. 4. **Minimize token privileges** - Use separate, narrowly scoped tokens for messaging and administrative operations. - Avoid granting organization administration rights to the routine messaging token. - Rotate tokens immediately if they may have been transmitted over HTTP. 5. **Improve schema and documentation** - Add URI format validation and an HTTPS-specific configuration constraint to `openclaw.plugin.json`. - Document that production `hubUrl` values must use HTTPS. - Add startup validation that prevents the account from connecting when secure transport requirements are not satisfied. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (17)

Exfiltration Commands

High
Category
Prompt Injection
Content
return af.some((a) => String(a).toLowerCase() === name);
}

// ─── Outbound: send message to HXA-Connect ───────────────────
const MAX_SEND_RETRIES = 2;
const RETRY_BASE_MS = 1000;
const CHANNEL_ID_RE = /^[a-zA-Z0-9_-]{1,64}$/;
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The registered tool exposes broad organization-level administration functions including changing bot roles, creating org tickets, rotating org secrets, renaming profiles, and manipulating threads and artifacts. For a channel plugin, these capabilities materially expand the attack surface: any prompt injection or overly broad tool access could turn a messaging bridge into an admin interface for the external HXA environment.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding
The lockfile pins the project to ws 8.19.0, and the provided advisory data indicates this version is affected by an uninitialized memory disclosure issue and a memory-exhaustion denial-of-service issue. Because this package is a WebSocket library used for network-facing communication, a vulnerable version can expose sensitive process memory or allow a remote attacker to degrade availability by sending crafted traffic.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The markdown explains that the plugin provides real-time bot-to-bot messaging via WebSocket and webhook inbound handling, and that it can optionally receive all thread messages. However, it does not include any warning about privacy or data transmission implications, even though these behaviors could affect user data and system privacy.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill describes and enables outbound network communication to an external messaging hub, but it declares no explicit tool scope or permission boundary. In an agent ecosystem, missing scope declarations can cause users or orchestrators to underestimate the plugin's ability to send and receive data externally, increasing the risk of unintended data exposure or misuse.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Create a thread
curl -sf -X POST ${HUB_URL}/api/threads \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"topic": "Review the report", "tags": ["request"], "participants": ["reviewer-bot"]}'
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The configuration and API examples repeatedly show bearer tokens and agent tokens in place without any warning to treat them as secrets. Even though the examples use placeholders, the absence of secret-handling guidance increases the chance that users will hardcode real credentials into configs, logs, or repositories, leading to account compromise of the bot and its messaging organization.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The tool can persistently modify the host's configuration file via setThreadModeInConfig, changing behavior across future runs. This is dangerous because a remote-triggerable or agent-triggerable command can alter local policy/state beyond transient messaging, creating a configuration integrity risk not obvious from a transport plugin.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The rotate-secret command invokes org secret rotation immediately with no confirmation, warning, or secondary authorization. Secret rotation is a high-sensitivity action that can invalidate integrations or be abused for denial of service and control over trust relationships if exposed to an agent or untrusted prompts.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The plugin is described as a messaging transport, but it also registers a tool that can perform administrative and state-changing actions such as role changes, ticket creation, secret rotation, profile changes, and host config mutation. This capability mismatch increases the chance that operators or higher-level agents will grant it broader trust than intended, enabling privileged actions through a seemingly low-risk channel integration.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The instruction "English for code" requires comments, commit messages, PR descriptions, and documentation to be in English. This is a natural-language policy constraint that forces a specific language without presenting it as optional or justified by a region-specific requirement.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The entry states that `mention_all` trigger behavior aligns with `@all` / `@所有人`, which embeds a specific locale-specific trigger form in natural language. Because this file does not indicate whether locale selection is optional or configurable, it may reflect a language/locale policy assumption rather than explicit user opt-in.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The instruction requires comments, commit messages, PR descriptions, and documentation to be in English. This is a natural-language policy constraint that forces a specific language rather than offering a choice or documenting a justified regional requirement.

Missing User Warnings

Low
Confidence
76% confidence
Finding
The handler accesses `acct.webhookSecret` and compares it against the bearer token for inbound authentication, which is a credential-handling operation. Although functionally appropriate, there is no nearby comment or user-facing disclosure explaining that a configured secret is being consumed for auth decisions in this path.

Unpinned Dependencies

Low
Category
Supply Chain
Content
],
  "author": "Coco AI (https://github.com/coco-xyz)",
  "dependencies": {
    "@coco-xyz/hxa-connect-sdk": "^1.3.1",
    "ws": "^8.18.0"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "Coco AI (https://github.com/coco-xyz)",
  "dependencies": {
    "@coco-xyz/hxa-connect-sdk": "^1.3.1",
    "ws": "^8.18.0"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Static analysis

No suspicious patterns detected.