Back to skill

Security audit

stock-assistant

Security checks for vulnerabilities and agentic risk

Overview

This stock assistant has a coherent purpose, but its notification feature can send sensitive holdings and profit data to broad external webhook destinations and handles Feishu secrets through command-line arguments.

Review carefully before installing. Use only trusted Feishu webhook URLs, avoid sending holdings or P&L to shared chats unless intentional, do not put real app secrets directly in shell commands or scheduled jobs, protect the local trades database and CSV exports, and be cautious importing or opening CSV files from untrusted sources.

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

T09 · Insecure Skill Coding Practices

Error
Location
fetcher.py:699
Finding

Private Portfolio Data Can Be Sent to Arbitrary HTTP Endpoints

Content
View full analysis
bool: """Send a message to Feishu. Supports: 1. Webhook URL 2. App ID + Secret """ import requests # Webhook method if webhook and webhook.startswith('http'): payload = { "msg_type": "text", "content": { "text": message } } try: response = requests.post(webhook, json=payload, timeout=30) return response.status_code == 200 except Exception as e: print(f"Send failed: {e}") return False return False ``` The original source uses Chinese comments and messages, but the executable condition is: ```python if webhook and webhook.startswith('http'): response = requests.post(webhook, json=payload, timeout=30) ``` `main.py:164-194`: ```python for code in codes: code = code.strip() if not code: continue # Retrieve quote result = fetcher.get_quote(code) # Retrieve local position position = trader.get_position(code) # Generate a card containing position information message = fetcher.format_table(result, position) messages.append(message) # Combine multiple cards full_message = messages[0] if len(messages) == 1 else json.dumps({ 'config': {'wide_screen_mode': True}, 'header': {'title': {'tag': 'plain_text', 'content': '📊 Multiple stock quotes'}, 'template': 'blue'}, 'elements': [{'tag': 'div', 'text': {'tag': 'lark_md', 'content': m}} for m in messages] }) if args.webhook: text_content = "\n\n---\n\n".join([ json.loads(m).get('elements', [])[0].get('text', {}).get('content', '') if m.startswith('{ ...[truncated 3603 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
notify_job.py:5
Finding

Feishu Application Secret Is Exposed Through Command-Line Arguments

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:67
Finding

Untrusted CSV Fields Are Exported Without Spreadsheet Formula Neutralization

Content
View full analysis
int: """Export trade records to CSV.""" trades = self.db.get_trades(code) with open(file_path, 'w', encoding='utf-8-sig', newline='') as f: fieldnames = [ 'Date', 'Time', 'Stock Code', 'Stock Name', 'Direction', 'Quantity', 'Average Price', 'Amount', 'Commission', 'Other Fees', 'Stamp Tax', 'Transfer Fee' ] writer = csv.DictWri ...[truncated 2626 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
db.py:25
Finding

Sensitive Financial Files Are Created Without Explicit Restrictive Permissions

Content
View full analysis
int: """Export trade records to CSV.""" trades = self.db.get_trades(code) with open(file_path, 'w', encoding='utf-8-sig', newline='') as f: ``` ### Technical Analysis The SQLite database and exported CSV files contain detailed financial information, including trade dates, stock codes, share quantities, prices, fees, costs, and holdings. The code does not explicitly set restrictive filesystem permissions for: - The `data` directory. - The SQLite database. - CSV exports. Permissions therefore depend on the process umask and inherited directory access controls. In a normal single-user environment with a restrictive umask, this may not be exploitable. In shared systems, containers with mounted volumes, or environments using permissive defaults, the resulting files may be readable by other local principals. ### Attack Path 1. The program runs in a shared environment with a permissive umask or broadly accessible parent directory. 2. `os.makedirs` creates the data directory using default permissions. 3. `sqlite3.connect` creates `trades.db`, or `open` creates an exported CSV, using permissions derived from that environment. 4. Another local user or process with filesystem access reads the resulting file. 5. The reader obtains detailed trade history and portfolio information. ### Impact Ass ...[truncated 345 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill context makes this more dangerous because stock holdings and P&L are financially sensitive, yet the documentation frames use around local querying and management while also supporting external push workflows. Users may not realize that watchlists, quotes, or position-related outputs can be batch-sent to third-party recipients.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill context makes this more dangerous because stock holdings and P&L are financially sensitive, yet the documentation frames use around local querying and management while also supporting external push workflows. Users may not realize that watchlists, quotes, or position-related outputs can be batch-sent to third-party recipients.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill context makes this more dangerous because stock holdings and P&L are financially sensitive, yet the documentation frames use around local querying and management while also supporting external push workflows. Users may not realize that watchlists, quotes, or position-related outputs can be batch-sent to third-party recipients.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill advertises network, file read, and file write behavior through its documented commands and data storage, but it does not declare any explicit tool scope or permission boundaries. This increases the risk of over-broad execution in an agent environment because consumers cannot tell which capabilities are intended or authorized.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documented delete command performs a destructive state-changing action on stored trade records, but there is no warning about permanence, backup, or confirmation. In a portfolio-tracking context, accidental deletion can corrupt financial history and distort P&L calculations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation introduces Feishu notification and push commands without integrating them into the earlier capability summary, which creates incomplete security disclosure. In a finance-related skill, even quote and watchlist data may be sensitive when transmitted to external endpoints or chats.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill documents sending stock information to Feishu via webhook or private chat, including use of app credentials and recipient identifiers, but gives no privacy or transmission warning. This is risky because users may expose portfolio-related information or mishandle secrets when using external messaging channels.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The CSV headers and values are entirely in Chinese, including field names like 成交日期 and 币种, with no indication that alternative language or locale formats are supported. Per the policy, forcing a specific language or locale without user choice is a natural-language policy violation unless clearly documented as region-specific, which is not present in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code defines deletion operations for a single trade and for all trades, including a bulk irreversible delete in delete_all_trades, but provides no confirmation prompt, logging, or explicit warning comment/docstring beyond a generic description. For code files, destructive or irreversible operations should include some form of user disclosure unless the warning is provided elsewhere, which is not evident in this file.

Content

No source excerpt is available for this finding.

Tainted flow: 'url' from requests.get (line 452, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · fetcher.py (reported line 289)May include surrounding context.

python
full_code = f'{market}{symbol}'
        url = f'https://qt.gtimg.cn/q={full_code}'
        
        response = requests.get(url, headers=self.headers, timeout=10)
        response.encoding = 'gbk'
        content = response.text
        return self._parse(content, symbol, market)

Tainted flow: 'url' from requests.get (line 452, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · fetcher.py (reported line 395)May include surrounding context.

python
full_code = f'{market}{symbol}'
        url = f'https://qt.gtimg.cn/q={full_code}'
        
        response = requests.get(url, headers=self.headers, timeout=10)
        response.encoding = 'gbk'
        content = response.text
        return self._parse(content, symbol, market)

Tainted flow: 'url' from requests.get (line 452, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · fetcher.py (reported line 454)May include surrounding context.

python
full_code = f'{market}{symbol}'
        url = f'https://qt.gtimg.cn/q={full_code}'
        
        response = requests.get(url, headers=self.headers, timeout=10)
        response.encoding = 'gbk'
        content = response.text
        return self._parse(content, symbol, market)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file includes outbound Feishu messaging capabilities that are not disclosed in the stated skill purpose focused on quote lookup, records, P&L, and CSV. Hidden or undeclared communication features increase the risk of unexpected external data transmission and reduce the user's ability to make informed trust decisions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Feishu webhook and private-message support is not obviously necessary for a stock assistant whose described scope is local analysis and quote retrieval. This mismatch makes the external-send capability more suspicious because it broadens the data flow surface beyond the expected feature set.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The webhook sender transmits message content to an arbitrary externally supplied URL with no user-facing disclosure at the call site. In a skill that primarily handles quotes and local trading records, this creates a meaningful risk of silent exfiltration of portfolio or analysis data to third-party endpoints.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Posting arbitrary message text to a user-supplied webhook is an external transmission channel that can be abused to exfiltrate data if upstream callers pass sensitive content. This is more concerning because the declared skill scope does not mention outbound notification or sharing behavior.

Content

Scanner excerpt · fetcher.py (reported line 717)May include surrounding context.

python
}
        }
        try:
            response = requests.post(webhook, json=payload, timeout=30)
            return response.status_code == 200
        except Exception as e:
            print(f"发送失败: {e}")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This function sends app credentials to Feishu to obtain a token, then transmits recipient identifiers and message content without explicit warning or approval in the function itself. Because the skill may process trading records and profit/loss data, the ability to relay that information externally increases confidentiality risk and broadens the blast radius of misuse or compromise.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

This is the same sensitive external-authentication behavior flagged above at the token request line. While not inherently malicious, it is a real security-relevant data flow because credentials are transmitted off-box and the capability is outside the narrow core purpose described for the skill.

Content

Scanner excerpt · fetcher.py (reported line 748)May include surrounding context.

python
try:
        # 1. 获取 access_token
        resp = requests.post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', json={
            'app_id': app_id,
            'app_secret': app_secret
        }, timeout=30)

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

This is the same sensitive external-authentication behavior flagged above at the token request line. While not inherently malicious, it is a real security-relevant data flow because credentials are transmitted off-box and the capability is outside the narrow core purpose described for the skill.

Content

Scanner excerpt · fetcher.py (reported line 748)May include surrounding context.

python
try:
        # 1. 获取 access_token
        resp = requests.post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', json={
            'app_id': app_id,
            'app_secret': app_secret
        }, timeout=30)

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The code sends message payloads to Feishu's messaging API, creating a direct outbound path for any supplied content. In a stock-assistant context that may handle holdings, costs, and profit/loss information, this can leak financially sensitive data to an external platform if invoked without clear user intent and safeguards.

Content

Scanner excerpt · fetcher.py (reported line 770)May include surrounding context.

python
content = json_mod.dumps({"text": message})
        
        # 3. 直接用 open_id 发送消息
        msg_resp = requests.post(f'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id', headers={
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }, json={

Tainted flow: 'content' from requests.get (line 397, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
82% confidence
Finding

The function forwards message content to Feishu without validating that the content is safe or expected for the selected recipient. In this skill, quote data may originate from external providers and can be retransmitted to another external service, creating a data-exfiltration and unreviewed third-party relay path if upstream content or caller input is sensitive.

Content

Scanner excerpt · fetcher.py (reported line 770)May include surrounding context.

python
content = json_mod.dumps({"text": message})
        
        # 3. 直接用 open_id 发送消息
        msg_resp = requests.post(f'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id', headers={
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }, json={

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The delete command removes trade records immediately based solely on an ID, with no confirmation, preview, or undo path. This creates a realistic risk of accidental destructive actions, especially in CLI usage, scripts, or when IDs are mistyped, leading to integrity loss of financial records.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes the skill as an A-share assistant for quote lookup, trade record management, position/P&L calculation, and CSV import/export. This file additionally implements a notify command that formats stock data and sends it to Feishu via webhook or private messaging, which is a separate outbound messaging/integration capability not mentioned in the declared purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The notify command can transmit quote and position-derived portfolio information to external Feishu endpoints without any explicit privacy notice, confirmation, or data minimization. Users may unintentionally disclose holdings or financial context to a third party, especially when using webhooks or shared chat destinations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Sending messages to Feishu groups or private chats requires external network communication and handling of app credentials/recipient identifiers. That capability is not an obvious requirement for querying A-share quotes, managing trades, calculating P&L, or CSV import/export as stated in the manifest.

Content

No source excerpt is available for this finding.