Back to skill

Security audit

同花顺 iFinD 接入 Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent iFinD financial-data connector, but it handles long-lived tokens and optional external routing with under-scoped destinations and weak disclosure.

Install only if you are comfortable letting the skill cache iFinD API tokens locally. Do not paste or run tokens in visible command lines if your environment logs commands, do not set custom base URLs unless you fully trust them, and leave optional LLM routing disabled for confidential financial queries unless you accept sending query text to that provider.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/runtime/tonghuashun_ifind_skill/auth.py:80
Finding

Caller-Controlled API Base URL Can Exfiltrate iFinD Credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/ifind_cli.py:107-114, scripts/ifind_cli.py:180-183, scripts/ifind_cli.py:218-242, scripts/runtime/tonghuashun_ifind_skill/auth.py:80-92, and scripts/runtime/tonghuashun_ifind_skill/client.py:25-44
Vulnerability Type: Unrestricted credential transmission to a caller-controlled network destination
Risk Level: High

Vulnerable Code

scripts/ifind_cli.py:107-114:

python
auth_refresh = subparsers.add_parser("auth-set-refresh-token")
auth_refresh.add_argument("--refresh-token", required=True)
auth_refresh.add_argument("--base-url", default=DEFAULT_BASE_URL)

api_common = argparse.ArgumentParser(add_help=False)
api_common.add_argument("--base-url", default=DEFAULT_BASE_URL)
api_common.add_argument("--payload", default="{}")

scripts/ifind_cli.py:180-183:

python
bundle = exchange_refresh_token(
    args.refresh_token,
    base_url=args.base_url,
)

scripts/runtime/tonghuashun_ifind_skill/auth.py:80-92:

python
def exchange_refresh_token(
    refresh_token: str,
    *,
    base_url: str,
    timeout: float = 10.0,
    now: Callable[[], datetime] | None = None,
) -> TokenBundle:
    response = requests.post(
        f"{base_url.rstrip('/')}/get_access_token",
        json={},
        headers={"Content-Type": "application/json", "refresh_token": refresh_token},
        timeout=timeout,
    )
    response.raise_for_status()

scripts/runtime/tonghuashun_ifind_skill/client.py:25-44:

python
def api_call(
    self,
    endpoint: str,
    payload: dict[str, object],
    access_token: str,
    token_source: str,
) -> dict[str, object]:
    normalized_endpoint = self._normalize_endpoint(endpoint)
    url = f"{self.base_url}{normalized_endpoint}"
    headers = {"Content-Type": "application/json", "access_token": access_token}
    timestamp = format_timestamp(self._now())

  
...[truncated 2373 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove --base-url from production authentication and data-query commands. Use a fixed official iFinD HTTPS origin.
  2. If endpoint configurability is operationally required, parse the URL and strictly allowlist approved hostnames, schemes, and ports.
  3. Require HTTPS and reject plaintext HTTP, URL-embedded credentials, fragments, unexpected ports, and malformed hostnames.
  4. Disable redirects for credential-bearing requests or validate every redirect target and reject cross-origin redirects.
  5. Separate test and production modes. A test mode that permits custom endpoints must use test credentials and require an explicit development-only setting.
  6. Add security tests proving that unapproved hosts, HTTP URLs, deceptive subdomains, and cross-origin redirects cannot receive tokens.
  7. Rotate any credentials that may already have been sent to an untrusted endpoint.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ifind_cli.py:102
Finding

iFinD Tokens Are Accepted Through Process-Visible Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/ifind_cli.py:102-109 and SKILL.md:42-51
Vulnerability Type: Sensitive credential exposure through process arguments
Risk Level: Medium

Vulnerable Code

scripts/ifind_cli.py:102-109:

python
auth_set = subparsers.add_parser("auth-set-tokens")
auth_set.add_argument("--access-token", required=True)
auth_set.add_argument("--refresh-token", required=True)
auth_set.add_argument("--expires-at", default=None)

auth_refresh = subparsers.add_parser("auth-set-refresh-token")
auth_refresh.add_argument("--refresh-token", required=True)
auth_refresh.add_argument("--base-url", default=DEFAULT_BASE_URL)

SKILL.md:42-51:

bash
python3 tonghuashun-ifind-skill/scripts/ifind_cli.py auth-set-refresh-token \
  --refresh-token "$IFIND_REFRESH_TOKEN"
bash
python3 tonghuashun-ifind-skill/scripts/ifind_cli.py auth-set-tokens \
  --access-token "$IFIND_ACCESS_TOKEN" \
  --refresh-token "$IFIND_REFRESH_TOKEN"

Technical Analysis

The documented authentication workflow passes access and refresh tokens as command-line options. Shell variable expansion places the actual secret values in the process argument vector.

Depending on the operating system and execution environment, command arguments may be visible to other local users, process-monitoring agents, container supervisors, diagnostic tools, audit systems, or automation logs. Agent frameworks may also record the full command invocation.

Environment-variable expansion does not protect the secret after command construction. Although the shell command references variables in source form, the child process receives the expanded token as an argument.

Attack Path

  1. A user or Agent follows the documented authentication command.
  2. The shell expands the token environment variable into the command argument vector.
  3. While the command is running, a local observer, monitoring ser ...[truncated 743 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove secret-bearing command-line options from the recommended authentication flow.
  2. Read tokens from standard input, preferably through an interactive hidden prompt such as getpass.getpass.
  3. For automation, accept secrets through a protected file descriptor or owner-readable secret file and delete temporary material promptly.
  4. If environment variables remain supported, read them directly inside the process rather than expanding them into command arguments.
  5. Ensure the CLI never logs, echoes, serializes, or includes token values in exception messages.
  6. Update SKILL.md and all reference examples to use the protected input mechanism.
  7. Configure Agent and process telemetry to redact known secret fields, and rotate tokens that may have entered historical command logs.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/runtime/tonghuashun_ifind_skill/llm_routing.py:116
Finding

Optional LLM Router Sends API Key and Full Financial Query to an Unrestricted URL

Content
View full analysis

Vulnerability Details

File Location: scripts/runtime/tonghuashun_ifind_skill/llm_routing.py:58-77 and scripts/runtime/tonghuashun_ifind_skill/llm_routing.py:116-147
Vulnerability Type: Unvalidated external destination for bearer credentials and user query data
Risk Level: Medium

Vulnerable Code

scripts/runtime/tonghuashun_ifind_skill/llm_routing.py:58-77:

python
enabled_raw = os.environ.get("IFIND_ROUTE_LLM_ENABLED", "").strip().lower()
api_key = (
    os.environ.get("IFIND_ROUTE_LLM_API_KEY")
    or os.environ.get("OPENAI_API_KEY")
    or ""
).strip()
if enabled_raw not in _TRUTHY:
    return None
if not api_key:
    return None

model = os.environ.get("IFIND_ROUTE_LLM_MODEL", "gpt-4o-mini").strip()
base_url = os.environ.get("IFIND_ROUTE_LLM_BASE_URL", cls.base_url).strip()
timeout = _float_from_env("IFIND_ROUTE_LLM_TIMEOUT", cls.timeout)
min_confidence = _float_from_env(
    "IFIND_ROUTE_LLM_MIN_CONFIDENCE",
    cls.min_confidence,
)
return cls(
    api_key=api_key,
    model=model,
    base_url=base_url.rstrip("/"),
    timeout=timeout,
    min_confidence=min_confidence,
)

scripts/runtime/tonghuashun_ifind_skill/llm_routing.py:116-147:

python
payload = {
    "model": config.model,
    "temperature": 0,
    "response_format": {"type": "json_object"},
    "messages": [
        {
            "role": "system",
            "content": (
                "你是 tonghuashun-ifind-skill skill 的自然语言路由器。"
                "只返回 JSON 对象,不要返回解释。所有数据查询都必须走同花顺 iFinD,"
                "不得规划腾讯、东方财富或其它公开源。"
            ),
        },
        {
            "role": "user",
            "content": _router_prompt(query=query, today=today),
        },
    ],
}
try:
    response = client.post(
        f"{config.base_url}/chat/completions",
        json=payload,
        headers={"Authorization": f"Bearer {config.api_key}"},
        time
...[truncated 2050 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS for all LLM routing endpoints and reject plaintext HTTP.
  2. Parse and validate the configured URL, rejecting embedded credentials, fragments, malformed hosts, and unexpected ports.
  3. Disable redirects or reject every redirect that changes the origin.
  4. Provide an allowlist of approved LLM providers. If arbitrary compatible endpoints must remain supported, require an explicit high-friction opt-in.
  5. Display or document a clear disclosure that the full query is sent to an external LLM provider, and obtain user or administrator consent before enabling the feature.
  6. Use provider-specific, least-privileged API keys with restricted quotas rather than broadly privileged credentials.
  7. Minimize transmitted content where possible and avoid sending unnecessary account, portfolio, or personally identifying information.
  8. Add automated tests covering HTTP rejection, hostile URLs, deceptive subdomains, and cross-origin redirects.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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 (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill claims all data comes from authenticated iFinD usage, but it also supports sending user queries to an external OpenAI-compatible LLM for routing. That creates a real data-flow expansion: potentially sensitive financial queries may leave the iFinD-only trust boundary and be transmitted to a third party using separate credentials, which users would not reasonably infer from the description.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares no explicit tool scope or permission boundaries even though its documented behavior requires environment access, filesystem reads/writes for token caching, and network access. In an agent ecosystem, missing scope declarations increase the chance of overbroad execution or silent access to sensitive resources beyond what users expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the agent to ask users to paste a refresh token directly into chat, but a refresh token is a credential-like secret that can often mint new access tokens. Collecting it through conversational channels materially raises the risk of credential leakage through chat logs, telemetry, screenshots, or downstream model processing.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The default prompt activates the skill for a very broad set of finance-related requests and strongly steers the agent to prefer this skill first. Overly broad activation can cause the agent to invoke the skill in situations where it is not necessary, leading to inappropriate collection or handling of sensitive iFinD authentication material and reducing user choice or safer fallback behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file is written as operational guidance for agents and begins with Chinese-only instructions such as '这份文档专门给 Agent 看。' There is no opt-in, alternative language option, or justification that the skill is region- or language-restricted, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation instructs users to enable optional LLM routing and provide an API key, but it does not warn that user queries may be transmitted to an external model provider. In a financial-data skill, queries can contain sensitive investment research, account-related context, or proprietary trading interests, so silent third-party transmission creates a real confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger examples for stock queries are broad colloquial phrases that can overlap with ordinary conversation, making unintended routing plausible. In this skill, accidental invocation would not directly cause code execution, but it could send an unintended financial-data query to iFinD, producing irrelevant results, privacy leakage of user intent, or confusing downstream actions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Vague index-snapshot triggers like generic requests to 'look at the market' or 'look at indices' lack clear boundaries and can match casual dialogue that is not meant to invoke a financial data workflow. Given this skill is restricted to iFinD data after authentication, the main risk is misrouting and unintended authenticated queries rather than provider escape, but that still creates reliability and potential data-exposure concerns.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The file begins with Chinese-only usage instructions and provides a fixed Chinese 'standard guidance' script for the agent. There is no indication that the user may choose another language or that the locale restriction is required for a documented region-specific compliance reason.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs the agent to ask the user for a long-lived iFinD refresh_token and to inject/store it via CLI commands, but it does not warn that these tokens are sensitive credentials equivalent to account access. In an agent setting, this increases the risk of credential exposure through chat logs, shell history, process lists, local config files, or downstream tool logging, which could allow unauthorized access to the user's iFinD account and data entitlements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file is entirely written as operational guidance in Chinese for the agent, with no indication that the agent should match the user's preferred language or offer a locale choice. Per the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The CLI persists access and refresh tokens to a local state file, and this file does not itself provide any warning, consent step, or visible safeguard around that storage. In a financial-data skill, stored tokens can grant continued API access and may be exposed through weak filesystem permissions, backups, or multi-user environments, so silent persistence increases credential-compromise risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code sends a user-supplied refresh token to a remote endpoint via exchange_refresh_token, with the destination partly controlled by --base-url and no user-facing disclosure in this file. Refresh tokens are highly sensitive because they can mint new access tokens, so transmitting them—especially to an overrideable endpoint—creates credential exfiltration risk if the endpoint is misconfigured or malicious.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The hard-coded default base URL points to an external OpenAI-compatible service, confirming that the skill is designed to transmit data outside the iFinD environment. In the context of a skill advertised as using authenticated iFinD data, this materially broadens the data handling surface and introduces third-party exposure risk.

Content

Scanner excerpt · scripts/runtime/tonghuashun_ifind_skill/llm_routing.py (reported line 52)May include surrounding context.

python
class LLMRoutingConfig:
    api_key: str
    model: str
    base_url: str = "https://api.openai.com/v1"
    timeout: float = 12.0
    min_confidence: float = 0.65

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code sends user queries to an external OpenAI-compatible chat completion endpoint for routing, despite the skill description stating that all data must come from authenticated iFinD. Even if the external model is only used for intent classification rather than final data retrieval, it still introduces off-platform processing of user input and expands the trust boundary beyond what the skill claims.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The natural-language system instruction is written to force a specific Chinese-language routing behavior and provider policy, with no apparent user opt-in or locale selection. Per the policy, forcing a specific language or locale without user choice can be a natural-language policy violation unless clearly justified and documented.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The router prompt embeds the user's query verbatim into the payload sent to the external model, which can disclose sensitive financial intent or proprietary information to a third party. In a financial-data skill, users may enter confidential symbols, investment theses, or portfolio-related text, making this context more sensitive than a generic chatbot.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code transmits raw user query text to an external LLM API without any indication here of notice, consent, or data minimization. User financial queries may contain sensitive holdings, watchlists, strategies, or account-related context, so silent third-party transmission creates a privacy and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The routing logic is built around Chinese-only query templates, aliases, and pattern matching, and the user-facing fallback notes are also only in Chinese. This effectively enforces a specific language/locale behavior without any explicit user opt-in or documented justification in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations in natural language content. This file appears to force a single language for all instructions and examples, with no opt-in, alternative language, or documented reason that the skill is limited to Chinese-speaking users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code sends the provided payload to a remote endpoint and includes an access token in request headers, which is a safety-relevant network operation involving potentially sensitive user or system data. There is no confirmation prompt, user-facing log/print, or inline warning in this file disclosing that data and credentials are being transmitted.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The stated purpose is to provide Tonghuashun iFinD financial data after authentication, but this module loads IFIND_ROUTE_LLM_API_KEY or OPENAI_API_KEY from environment variables to enable a separate LLM router. Accessing unrelated third-party credentials is not an obvious requirement of an iFinD market-data skill as described in the manifest. This introduces an additional capability and trust dependency outside the declared purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The skill accesses credentials from environment variables including IFIND_ROUTE_LLM_API_KEY and OPENAI_API_KEY. Access to sensitive credentials is in scope for missing-warning findings when there is no accompanying comment, docstring, or other disclosure explaining the behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.