Back to skill

Security audit

WeChat Official Accounts Article Details API

Security checks for vulnerabilities and agentic risk

Overview

This skill is a narrow JustOneAPI wrapper, but it handles the required API token in ways that can expose it through process arguments and URL logs.

Review before installing if the JustOneAPI token has broad permissions, billing impact, or long lifetime. Prefer a narrowly scoped, revocable token, avoid shell history and process telemetry where possible, and assume the token may appear in API gateway or server logs because it is sent in the URL query string.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
bin/run.mjs:27
Finding

API Token Exposed Through Command-Line Arguments and URL Query Parameters

Content
View full analysis
"}' ``` From `bin/run.mjs:27-35`: ```js { "defaultValue": null, "description": "Access token for the API.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" } ``` From `bin/run.mjs:70-93`: ```js const baseUrl = manifest.baseUrl; const url = new URL(operation.path, ensureBaseUrl(baseUrl)); applyPathParams(operation, params, url); applyQueryParams(operation, params, url); const requestInit = { headers: { "accept": "application/json", }, method: operation.method, }; if (operation.requestBody && params.body !== undefined) { requestInit.body = JSON.stringify(params.body); requestInit.headers["content-type"] = operation.requestBody.contentType || "application/json"; } let response; try { response = await fetch(url, requestInit); } catch (error) { fail("Network request failed.", { cause: error instanceof Error ? error.message : String(error), operationId: operation.operationId, }); } ``` From `bin/run.mjs:173-185`: ```js function injectToken(operation, params, cliToken) { const tokenParam = operation.parameters.find((parameter) => parameter.name === "token"); if (!tokenParam || params.token !== undefined) { return; } if (!cliToken) { fail("--token is required for this operation.", { operationId: operation.operationId, }); } params.token = c ...[truncated 3323 chars]
Remediation
View remediation
"}' ``` 5. **If the upstream API mandates query-string authentication**, explicitly document that limitation and apply compensating controls: - Use narrowly scoped and short-lived tokens. - Redact `token` from proxy, gateway, application, and monitoring logs. - Never print or include the complete request URL in errors. - Disable shell history for credential-bearing commands. - Rotate any token suspected of appearing in logs or process telemetry. - Restrict access to operational logs and apply short retention periods. 6. **Add automated safeguards.** Include tests that verify secrets do not appear in command-line examples, emitted errors, standard output, diagnostic events, or URLs when header authentication is available. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This finding is triggered by the presence of an access token parameter, which by itself is not malicious; however, in this skill the credential is handled insecurely because it is transported as a URL query parameter. In the context of a simple API wrapper, this increases the chance of credential exposure through operational logging rather than indicating deliberate credential theft logic.

Content

Scanner excerpt · bin/run.mjs (reported line 20)May include surrounding context.

js
"parameters": [
        {
          "defaultValue": null,
          "description": "Access token for the API.",
          "enumValues": [],
          "location": "query",
          "name": "token",

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The API design requires an access token to be sent as a query parameter, which is a real credential-handling weakness. Query-string tokens are commonly exposed through logs, browser history, intermediary proxies, analytics systems, and referrer leakage, increasing the chance of credential disclosure. In this skill context, the endpoint only retrieves article details, so the direct blast radius is limited to the API account or quota associated with the token rather than arbitrary code execution.

Content

Scanner excerpt · generated/operations.json (reported line 15)May include surrounding context.

json
"parameters": [
        {
          "defaultValue": null,
          "description": "Access token for the API.",
          "enumValues": [],
          "location": "query",
          "name": "token",

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · generated/operations.md (reported line 19)May include surrounding context.

md
| Name | In | Required | Type | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `token` | `query` | yes | `string` | n/a | Access token for the API. |
| `articleUrl` | `query` | yes | `string` | n/a | The URL of the Weixin article. |

### Request body

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes a Node helper that performs outbound API requests, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. This creates a least-privilege and transparency gap: a host agent or reviewer cannot easily determine from the skill declaration that network access is required, which can enable unintended external data exfiltration or policy bypass if the runtime permits undeclared capabilities.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill explicitly defines the API token as a query parameter and later appends all query parameters to the request URL. Tokens in URLs are routinely exposed through logs, browser/history artifacts, monitoring systems, proxies, and error telemetry, making accidental credential disclosure substantially more likely than if the token were sent in an Authorization header.

Content

No source excerpt is available for this finding.