Back to skill

Security audit

onebot QQ群管理

Security checks for vulnerabilities and agentic risk

Overview

This QQ group admin skill exposes broader bot-control and local-file-reading capability than its user-facing purpose clearly scopes.

Review before installing. Only use this skill in a tightly controlled local environment with a dedicated low-privilege bot account, rotate the embedded OneBot token, remove the hardcoded fallback, restrict actions and groups with an allowlist, and remove the arbitrary '@/path' file-read feature before trusting it with real QQ groups or local secrets.

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
scripts/onebot-action.js:21
Finding
Unrestricted OneBot API Invocation Without an Action Allowlist<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onebot-action.js`, lines 21-25 and 72-76 **Vulnerability Type**: Missing authorization boundary and unrestricted privileged API dispatch **Risk Level**: High ### Vulnerable Code ```javascript function parseArgs(argv) { const action = argv[2]; if (!action) { console.error('Usage: node onebot-action.js <action> [key=value ...]'); console.error('Special: key=@/path/to/file reads file content as value'); process.exit(1); } ``` ```javascript ws.on('open', () => { const payload = { action, params, echo }; ws.send(JSON.stringify(payload)); }); ``` ### Technical Analysis The command-line `action` value is accepted verbatim and transmitted directly to the authenticated OneBot WebSocket endpoint. There is no allowlist restricting actions to the group-administration operations described in `SKILL.md`, no validation of the target group, and no confirmation or authorization mechanism for destructive operations. Consequently, this script is not limited to the documented functions. A caller able to invoke it can dispatch any action supported by the connected OneBot implementation, including undocumented or implementation-specific extension APIs. The exact available operations depend on the NapCat/OneBot server, but they may extend beyond group administration to messaging, account operations, request handling, or other bot capabilities. The skill documentation says that sensitive actions should be confirmed, but this requirement is not enforced by code. Documentation-only guidance does not provide a security boundary. ### Attack Path 1. An attacker influences an agent prompt, automation input, or other caller that can execute this skill. 2. The attacker supplies an arbitrary action name instead of one of the documented group-management actions. 3. The attacker supplies any parameters required by that action. 4. The script connects using the configured OneBot credential. 5. It forwards ...[truncated 996 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define an explicit allowlist of permitted actions, such as: - `set_group_name` - `_send_group_notice` - `set_group_ban` - `set_group_whole_ban` - `set_group_kick` - `set_group_admin` - `set_group_card` - `set_group_special_title` - `set_group_portrait` - `delete_msg` - `get_group_info` - `get_group_member_list` - `get_group_member_info` 2. Reject every action not present in the allowlist before opening the WebSocket. 3. Add action-specific schemas that reject unknown parameters and validate identifiers, booleans, durations, paths, and string lengths. 4. Enforce an authorized group-ID allowlist rather than permitting arbitrary targets. 5. Require an explicit confirmation token or separate privileged execution path for destructive actions such as kicking members, changing administrators, deleting messages, and imposing bans. 6. Separate read-only and mutating operations into different entry points and credentials where supported. 7. Record security audit logs containing the caller, action, target, and result, while excluding credentials and sensitive content. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onebot-action.js:43
Finding
Arbitrary Local File Read and Disclosure Through OneBot Parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onebot-action.js`, lines 43-47 and 72-76 **Vulnerability Type**: Arbitrary file read with network or messaging disclosure **Risk Level**: High ### Vulnerable Code ```javascript // Read from file: key=@/path/to/file if (val.startsWith('@/')) { const fs = require('fs'); val = fs.readFileSync(val.slice(1), 'utf8').trim(); } ``` ```javascript ws.on('open', () => { const payload = { action, params, echo }; ws.send(JSON.stringify(payload)); }); ``` ### Technical Analysis Any parameter value beginning with `@/` is interpreted as an absolute filesystem path. The script reads that file synchronously with the privileges of the Node.js process and substitutes its entire contents into the outgoing OneBot request. There is no path allowlist, base-directory restriction, file-type validation, size limit, symbolic-link defense, or check that the selected action legitimately needs file content. Because the action is also unrestricted, a caller can combine the file-read feature with an API action that publishes or transmits text. Alternatively, if `ONEBOT_WS_URL` points to an attacker-controlled WebSocket endpoint, the request itself discloses the file content to that endpoint. The help text exposes the feature, but `SKILL.md` does not document its security implications. The capability is unnecessary for most documented group-administration operations. ### Attack Path One viable attack path is: 1. The attacker gains influence over arguments passed to the script. 2. The attacker selects a readable sensitive file using a parameter such as `content=@/path/to/sensitive-file`. 3. `readFileSync()` reads the file under the privileges of the process running the skill. 4. The file contents replace the original parameter value. 5. The script serializes those contents into the OneBot payload. 6. The contents are disclosed either: - to the configured WebSocket server directly; or - through a supported OneB ...[truncated 911 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the generic `@/path` file-reading feature unless it is strictly required. 2. For actions that genuinely require files, implement action-specific handling rather than accepting file content for every parameter. 3. Restrict files to a dedicated upload directory resolved with `fs.realpathSync()`. 4. Verify that the resolved path remains inside the approved directory and reject path traversal and symbolic links escaping that directory. 5. Enforce file-type, extension, ownership, permission, and maximum-size restrictions. 6. Prefer passing an approved file reference to the local OneBot service rather than reading and embedding arbitrary contents. 7. Never permit file-derived values in messaging, notice, URL, token, action, or destination parameters. 8. Restrict `ONEBOT_WS_URL` to an administrator-controlled configuration and validate it against an endpoint allowlist. 9. Run the skill as a dedicated, unprivileged operating-system user with access only to required workspace files. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onebot-action.js:18
Finding
Hardcoded OneBot Authentication Token Exposed in Source Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onebot-action.js`, lines 18-19 **Vulnerability Type**: Hardcoded credential and plaintext secret storage **Risk Level**: High ### Vulnerable Code ```javascript const WS_URL = process.env.ONEBOT_WS_URL || 'ws://127.0.0.1:13001'; const WS_TOKEN = process.env.ONEBOT_WS_TOKEN || 'FTubmd6pc77aX~XK'; ``` The token is subsequently placed into the WebSocket URL: ```javascript const url = WS_TOKEN ? `${WS_URL}?access_token=${encodeURIComponent(WS_TOKEN)}` : WS_URL; const ws = new WebSocket(url); ``` ### Technical Analysis A functional-looking OneBot access token is embedded directly in the distributed source code as the default credential. Anyone who can read the project, its package history, backups, logs, or copied artifacts can recover this token. Because the script silently falls back to the embedded value when `ONEBOT_WS_TOKEN` is absent, installations may unknowingly share or continue using the exposed credential. Removing the token from the current file later would not invalidate copies retained in source-control history or previously distributed packages. The credential is also appended to the WebSocket URL query string. URLs are more likely than headers to be captured by debug output, proxy logs, monitoring systems, exception telemetry, or server access logs. ### Attack Path 1. An attacker obtains a copy of the skill package or reads the repository. 2. The attacker extracts the hardcoded token from line 19. 3. The attacker identifies or gains network access to the corresponding OneBot WebSocket service. 4. The attacker connects using the exposed token. 5. The attacker submits OneBot actions directly, bypassing the skill's intended workflow and confirmation guidance. If the service is bound only to loopback, exploitation additionally requires local execution, port forwarding, a proxy, SSRF-like network access, or a configuration change that exposes the service. If the same token is reused o ...[truncated 575 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Immediately revoke and rotate the exposed OneBot token. 2. Remove the hardcoded fallback and fail closed when `ONEBOT_WS_TOKEN` is missing. 3. Load the credential from an operating-system secret store, protected configuration file, or managed secret service. 4. Ensure secret files are readable only by the dedicated service account and are excluded from source control and package artifacts. 5. Purge the credential from source-control history and review prior releases, logs, and backups for exposure. 6. Avoid query-string authentication where the server supports an authorization header or another non-URL authentication mechanism. 7. Use a unique credential per deployment and apply the minimum OneBot permissions supported by the environment. 8. Restrict the WebSocket listener to trusted local processes or authenticated private networks. 9. Add automated secret scanning to development and release pipelines. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onebot-action.js:18
Finding
OneBot Credential and API Traffic Can Be Sent Over Unencrypted WebSocket Connections<![CDATA[ ## Vulnerability Details **File Location**: `scripts/onebot-action.js`, lines 18 and 61-63 **Vulnerability Type**: Cleartext transmission of authentication credentials and privileged API traffic **Risk Level**: Medium ### Vulnerable Code ```javascript const WS_URL = process.env.ONEBOT_WS_URL || 'ws://127.0.0.1:13001'; ``` ```javascript const url = WS_TOKEN ? `${WS_URL}?access_token=${encodeURIComponent(WS_TOKEN)}` : WS_URL; const ws = new WebSocket(url); ``` ### Technical Analysis The default connection uses the unencrypted `ws://` scheme, and the script accepts an arbitrary `ONEBOT_WS_URL` without requiring TLS for non-loopback destinations. The access token is placed in the URL, while all API actions, parameters, identifiers, and responses are sent over the same connection. The loopback default reduces exposure on a correctly isolated host, but the documented environment override permits remote endpoints. When a non-loopback `ws://` endpoint is configured, any party able to observe or modify the network path may capture the token and API data or tamper with requests and responses. The code does not validate the destination host, enforce `wss://` for remote connections, pin a certificate, or reject URLs containing unexpected components. ### Attack Path 1. A deployment configures `ONEBOT_WS_URL` with a remote `ws://` endpoint, or local traffic is intercepted by a sufficiently privileged local adversary. 2. The script appends the access token to the URL query string. 3. The WebSocket handshake and subsequent OneBot traffic traverse the connection without transport encryption. 4. An on-path attacker captures the token and sensitive request data. 5. The attacker reuses the token against the OneBot endpoint or modifies privileged API traffic in transit. ### Impact Assessment A successful interception can expose the OneBot credential, group and user identifiers, announcement or message content, and details of administrative actions. Credential th ...[truncated 327 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit `ws://` only when the resolved destination is a verified loopback address and the service is intentionally local. 2. Require `wss://` for every non-loopback endpoint. 3. Validate `ONEBOT_WS_URL` using the URL parser and reject unsupported schemes, embedded credentials, fragments, and unapproved hosts. 4. Configure strict TLS certificate verification; use certificate or public-key pinning for high-risk deployments where operationally appropriate. 5. Prefer authorization headers over URL query parameters if supported by the OneBot server. 6. Place remote OneBot services behind a private authenticated network and firewall them to approved clients. 7. Do not log complete connection URLs, and redact tokens from errors and diagnostics. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented purpose is limited to QQ group administration, but the skill behavior reportedly supports arbitrary OneBot API invocation and file/URL-backed parameters such as `set_group_portrait file=...`, which materially expands its reachable capability. In practice this can enable actions beyond group admin scope, including other account, friend, message, or bot operations, and can expose local file content or trigger unintended network access through the OneBot service while using authenticated WebSocket access not clearly disclosed in the description.

Ae1

High
Category
analysis-evasion
Content
通过 `scripts/onebot-action.js` 调用 napcat 的 OneBot 11 API 执行群管理操作。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script is presented as a QQ group-management utility, but it accepts any caller-supplied action and forwards it directly to the OneBot WebSocket API. This creates a capability mismatch: any workflow or agent that trusts the skill’s stated scope can be tricked into invoking broader OneBot operations than intended, potentially including sensitive bot, friend, group, or system-affecting APIs.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill exposes environment-derived capabilities via `ONEBOT_WS_URL` and `ONEBOT_WS_TOKEN` but does not declare any tool scope or permissions boundary. This weakens reviewability and allows the skill to authenticate to a local OneBot service with operator credentials without that privileged access being explicitly surfaced to users or policy controls.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The tool allows potentially destructive administrative actions to be executed immediately based only on command-line input, with no confirmation gate, policy check, or role restriction. In the skill context, this is more dangerous because group-management actions like bans, kicks, admin changes, or announcements can cause immediate operational harm if triggered accidentally, by prompt injection, or by a confused agent.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The '@/path/to/file' feature lets a caller read arbitrary local files and inject their contents into API parameters, which can then be transmitted over the WebSocket connection. In an agent setting, this is a local file disclosure primitive unrelated to normal group management and could expose secrets such as tokens, configs, SSH keys, or application data.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The file-reading shortcut silently converts user input into local file access and sends the resulting contents to the remote OneBot endpoint without any explicit warning at the point of use. In an agent or automation environment, this materially increases the risk of covert exfiltration because a seemingly ordinary parameter can become a secret-bearing payload.

Static analysis

No suspicious patterns detected.