Back to skill

Security audit

A Stock Watcher

Security checks for vulnerabilities and agentic risk

Overview

This stock-watching skill is mostly purpose-aligned, but it has Review-worthy issues around unauthenticated market data, local storage of portfolio data, and under-scoped notification helpers.

Review this skill before installing if you plan to use it for real investing. Treat its analysis as informational only, avoid entering sensitive portfolio details unless local plaintext storage is acceptable, and be cautious with notifications because message content can be sent to external DingTalk-style endpoints. Its market data is fetched over unauthenticated HTTP, so do not rely on it as an authoritative source for trading decisions.

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

T09 · Insecure Skill Coding Practices

Warning
Location
a_stock_watcher.py:115
Finding

Financial Market Data Retrieved over Unauthenticated Plaintext HTTP

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
notification.py:17
Finding

Caller-Controlled DingTalk Webhook URL Enables Arbitrary Outbound HTTP Requests

Content
View full analysis
bool: """ 通过钉钉机器人 Webhook 发送消息 """ if not webhook_url: print("[钉钉 Webhook] 未配置 Webhook URL") return False try: headers = {'Content-Type': 'application/json; charset=utf-8'} data = { "msgtype": "text", "text": { "content": message } } response = requests.post(webhook_url, headers=headers, json=data, timeout=10) result = response.json() ``` #### `notification.py:56-87` ```python def send_dingtalk_markdown(title: str, text: str, webhook_url: str = None, at_all: bool = False) -> bool: """ 发送钉钉 Markdown 消息 """ if not webhook_url: return False try: headers = {'Content-Type': 'application/json; charset=utf-8'} data = { "msgtype": "markdown", "markdown": { "title": title, "text": text }, "at": { "isAtAll": at_all } } response = requests.post(webhook_url, headers=headers, json=data, timeout=10) result = response.json() ``` ### Technical Analysis Both webhook functions send an outbound POST request to a URL supplied directly by the caller. The URL is not restricted to DingTalk domains and is not checked for: - An HTTPS scheme. - A permitted hostname or path. - Embedded credentials. - Loopback, private, link-local, multicast, or reserved IP addresses. - DNS rebinding. - Redirects to prohibited destinations. If an untrusted value can reach `webhook_url` through a future handler, API wrapper, configuratio ...[truncated 2212 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (33)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrase "日报" is overly generic and can easily match ordinary user requests for a daily report unrelated to stock monitoring. In an agent environment, this can cause unintended skill activation, leading to confusing behavior, irrelevant financial outputs, or accidental access to portfolio-related features when the user meant something else.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The phrase "风险评估" is ambiguous because it commonly refers to many domains such as health, insurance, cybersecurity, or compliance, not just investment profiling. This increases the chance that the skill intercepts unrelated requests and returns financial-risk questionnaire flows in the wrong context.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The triggers "投资组合" and especially "资产配置" are broad financial terms that may appear in many general conversations, educational queries, or enterprise contexts. Because this skill includes recommendation-style functionality, accidental activation could surface inappropriate investment guidance or portfolio outputs when the user's intent was broader or different.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The trigger phrases are broad natural-language commands such as querying prices, setting holdings, and watch actions, but the document does not define invocation boundaries or disambiguation rules. In an agent setting, this can cause accidental skill activation during ordinary conversation, potentially leading to unintended external API calls, state changes, or monitoring actions without clear user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill documents persistent holdings and automated monitoring features, but does not tell users that portfolio data may be stored or that market data requests may be sent to external providers. In a finance context, this creates privacy and consent risks because sensitive investment positions and behavior could be retained or transmitted without explicit notice.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The top-level documentation presents the skill as an "A 股盯盘技能" and describes data sources in that A-share framing. However, the implementation in get_stock_tencent explicitly accepts hk... and us... symbols and labels them as Hong Kong and US markets, which is a direct contradiction of the stated scope rather than a mere omission.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module description and all command formats are presented exclusively in Chinese, indicating the skill is designed to operate only in a specific language/locale. The file does not provide any user choice, fallback, or documented justification for this language restriction.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

With no manifest available, the strongest stated purpose comes from the file's own description and handler help text framing it as a stock-watching skill. The code imports and exposes additional capabilities such as daily reports, holdings management, risk profiling, valuation analysis, stop-loss/profit planning, and portfolio optimization, which materially exceed simple quote lookup and alerting.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The handler and help text require Chinese trigger phrases such as “查询”, “盯盘”, and “风险提示”, and no alternative language option is offered. This is a natural-language policy concern because it forces a specific language for interaction without user choice or an explicit documented constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script emits user-facing output entirely in Chinese, including the title and section headers, with no option for the user to select another language. This is a natural-language policy concern because it enforces a specific locale without opt-in or explanation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module persists sensitive investment data, including holdings and a notification identifier, to a predictable local JSON file in plaintext without any notice, access controls, or minimization. On a shared system or in an agent environment where workspace files may be exposed to other tools, users, logs, backups, or other tenants, this can leak private financial positions and identifiers.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module’s natural-language documentation and all user-facing messages are hard-coded in Chinese, and the code explicitly configures Chinese font handling. There is no indication that the skill offers a language choice or that this locale restriction is justified as a region-specific tool, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module title, descriptions, questions, and user-facing guidance are all written in Chinese, and there is no indication that users may choose another language or locale. This creates a natural-language locale constraint without opt-in, which matches the policy-violation category for language or locale restrictions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The function and docstring present the feature as modern portfolio optimization, but the implementation explicitly ignores correlations and uses a simplistic inverse-volatility heuristic. In an investment-advice skill, this can materially misstate diversification and risk, leading users to make unsafe allocation decisions based on false analytical claims.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · notification.py (reported line 41)May include surrounding context.

python
}
        }
        
        response = requests.post(webhook_url, headers=headers, json=data, timeout=10)
        result = response.json()
        
        if result.get("errcode") == 0:

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · notification.py (reported line 86)May include surrounding context.

python
}
        }
        
        response = requests.post(webhook_url, headers=headers, json=data, timeout=10)
        result = response.json()
        
        if result.get("errcode") == 0:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code performs an outbound HTTP POST to a DingTalk webhook containing the provided message content. Although there is success/failure logging, there is no warning or explanatory comment/docstring that this function transmits user-supplied data to an external service, which is the kind of safety-relevant disclosure required for network operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This function sends title, markdown text, and mention settings to a remote webhook via HTTP POST. The implementation logs only failures and lacks any explicit warning in code comments, docstrings, or visible user disclosure that content is being transmitted off-system.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file presents its interface, status messages, and reports exclusively in Chinese, including the module description and user-facing strings. Under the policy, forcing a specific language without opt-in or a documented regional constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python file contains module docstrings, class docstrings, and user-facing output in Chinese, with no indication that another language is supported or that the locale is configurable. 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.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README is entirely written in Chinese and all invocation examples and output formats assume Chinese input such as “查询 600036 行情” and Chinese-language responses. There is no indication that users may choose another language or that the locale restriction is optional, which creates a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

SQP-3 适用于所有文件类型。该文件的标题、说明、命令示例与注释均仅提供中文,没有说明这是面向特定中文环境的技能,也未提供用户语言选择,存在语言/地区策略上的潜在限制。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document presents a working StockAnalyzer unified interface and shows full_analysis('002892') as available at L61-L69. However, the roadmap later says 统一分析接口封装 is still in progress at L183-L186, which directly conflicts with the earlier claim that this capability is already implemented.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The API reference documents analyzer.compare(['002892', '600036']) as an available callable method at L227-L249. But the project status section lists 股票对比功能 as still in progress at L183-L186, so the documentation simultaneously says the feature exists and is not yet finished.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring says the function prioritizes Tencent first, then Eastmoney, then Sina, but elsewhere the file declares DATA_SOURCES = ["eastmoney", "tencent", "sina"] and multiple comments/documentation sections describe Eastmoney as the primary source. This creates conflicting intent/documentation about which upstream source is authoritative.

Content

No source excerpt is available for this finding.