Back to skill

Security audit

A股公众号大V

Security checks for vulnerabilities and agentic risk

Overview

The skill generally does the advertised A-share WeChat ranking lookup, but its API-key handling and persistent subscription changes need review before installation.

Install only if you are comfortable giving the skill a Redfox API key and allowing it to save local subscription state. Prefer REDFOX_API_KEY in the environment, avoid --api-key command examples, restrict any config file to owner-only permissions, and confirm account additions/removals before letting an agent run subscription actions.

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
scripts/fetch_astock_accounts.py:13
Finding
API Key Exposure Through Command-Line Arguments and Insecure Plaintext Configuration<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:42-43`, `scripts/fetch_astock_accounts.py:13,54-57,224,231`, `scripts/fetch_subscribed_updates.py:13,48-50,202,207` **Vulnerability Type**: API credential disclosure through process arguments, shell history, and insufficiently protected plaintext storage **Risk Level**: Medium ### Vulnerable Code Snippets `scripts/fetch_astock_accounts.py:13` ```python python3 fetch_astock_accounts.py --date 2026-06-15 --api-key ak_xxx ``` `scripts/fetch_astock_accounts.py:54-57` ```python def get_api_key(cli_key=None): """Get API key: CLI arg > env var > config file.""" if cli_key: return cli_key ``` `scripts/fetch_astock_accounts.py:231` ```python api_key = get_api_key(cli_key=args.api_key) ``` `scripts/fetch_subscribed_updates.py:13` ```python python3 fetch_subscribed_updates.py --api-key ak_xxx ``` `scripts/fetch_subscribed_updates.py:48-50` ```python def get_api_key(cli_key=None): if cli_key: return cli_key ``` `scripts/fetch_subscribed_updates.py:207` ```python api_key = get_api_key(cli_key=args.api_key) ``` The configuration instructions in `SKILL.md:43` also direct users to place the API key in `~/.qoder/apis/redfox.json` using ordinary shell redirection, without requiring owner-only file permissions. ### Technical Analysis Both network-facing scripts accept the Redfox API key directly as a command-line argument. Command-line arguments are not an appropriate secret-delivery mechanism because they may be: - Recorded in interactive shell history. - Visible to local process-monitoring utilities while the script is running. - Captured by command auditing, orchestration logs, debugging tools, or terminal session recording. - Retained in automation definitions or agent execution transcripts. The alternative configuration-file workflow stores the credential as plaintext. The documented creation procedure does not explicitly set the file mode to `0600`, verify ownership ...[truncated 2146 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--api-key` option and all command-line examples that place credentials in process arguments. 2. Prefer `REDFOX_API_KEY` from a controlled environment or an operating-system credential store. 3. If interactive entry is required, use a non-echoing prompt such as Python's `getpass.getpass()` and do not log the returned value. 4. Create the configuration directory and file with restrictive permissions: - Directory mode: `0700` - Credential file mode: `0600` 5. Before reading the configuration file, verify that: - It is a regular file rather than a symbolic link. - It is owned by the current user. - Group and other permission bits are not set. 6. Avoid printing, serializing, caching, or including the key in exception messages. 7. Update `SKILL.md`, both README files, and script usage examples to describe only secure credential-delivery methods. 8. Recommend narrowly scoped, revocable, and short-lived API credentials where supported. 9. Advise existing users who used the command-line option to remove affected shell-history and automation-log entries and rotate the exposed key. ]]>
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation describes use of environment variables, network access, local cache writes, and persistent subscription storage, but no permissions are explicitly declared. This creates a transparency and governance gap: an agent or reviewer may underestimate the skill’s ability to exfiltrate secrets, reach external services, or persist user-derived state on disk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared purpose is a date-based A-share ranking lookup, but the skill also documents persistent subscription management, local state mutation, cached-result reuse, and broader account/query behaviors. This mismatch undermines informed consent and review because users and orchestrators may invoke a seemingly read-only lookup skill that actually writes files, maintains state across sessions, and supports broader data access patterns.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The script implements persistent subscription management by reading and writing a local subscriptions.json file, which goes beyond the skill metadata's described purpose of retrieving ranking/account/article data. This creates undeclared stateful behavior and expands the skill's authority surface, so a caller could cause lasting data changes that users would not reasonably expect from a read-oriented ranking tool.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The add flow accepts AI-supplied JSON via --榜单-json, parses it, and uses its contents to modify persistent subscriptions without validating provenance, schema, or trust boundaries. In an agent context, this is risky because model-produced or prompt-injected data can directly drive durable state changes, enabling unauthorized or misleading subscription manipulation.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The file’s stated purpose is to return A股公众号大V/stock-public-account results, but a large portion of entries expand into unrelated categories such as券商、基金、行业协会 and other non-target accounts. This creates a data integrity and scope-poisoning issue: downstream agents may trust the dataset as curated for a narrower domain and make incorrect recommendations, filtering, or ranking decisions based on contaminated inputs.

Vague Triggers

Medium
Confidence
82% confidence
Finding
The README instructs activation on several broad natural-language phrases, which can cause the skill to trigger in conversations that merely mention A-share public accounts or influencers rather than explicitly requesting this tool. In an agent environment, overbroad invocation increases the chance of unintended data access, irrelevant tool use, and user confusion, even though this skill appears read-only and does not itself expose a direct exploit path.

Vague Triggers

Medium
Confidence
85% confidence
Finding
The trigger phrases are broad finance-related terms such as 'A股公众号' and '股市大V', which can overlap with ordinary discussion or analysis requests. Overbroad activation can cause the agent to invoke a networked, stateful skill unexpectedly, leading to unnecessary external calls, unintended data processing, or writes when the user did not intend tool usage.

Vague Triggers

Medium
Confidence
83% confidence
Finding
The subscription-update examples use natural phrases like '看订阅账号更新' or '推送今日更新' without strong constraints or confirmation gates. Because this operation queries persisted subscriptions and may reveal or act on prior state, ambiguous invocation increases the risk of accidental activation and unexpected disclosure of subscription-derived results.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The clear action immediately wipes an entire subscription category and persists the change with no confirmation, dry-run, or undo capability. In an agent-driven environment, accidental invocation, prompt confusion, or indirect tool misuse could permanently remove user data with little friction.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The remove action performs persistent deletion based on provided account names without requiring a pre-action confirmation or presenting a preview of affected entries. While narrower than clear, it still allows unintended state changes and can be abused or triggered accidentally in an agent workflow.

Missing User Warnings

Medium
Confidence
80% confidence
Finding
The script retrieves account/profile metadata from a remote service and then persists the aggregated account dataset locally as JSON without any explicit operator notice, retention controls, or minimization. In this skill context, the data appears to be public-facing公众号 account information rather than highly sensitive secrets, which reduces severity, but silent persistence still increases privacy, compliance, and accidental exposure risk on shared systems.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/api_guide.md:16