Back to skill

Security audit

A股持仓监控助手

Security checks for vulnerabilities and agentic risk

Overview

This A-share portfolio skill is mostly coherent, but it contains unsafe shell execution from portfolio menu input that can run unintended local commands.

Review this skill before installing or running it. Do not use the interactive menu with untrusted input, and prefer direct, validated script calls only after the shell execution is fixed. Be aware it stores holdings locally, contacts Tencent Finance for quotes, uses HTTP for some market data, and does not actually implement automatic alerts as advertised.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_monitor.py:34
Finding

Shell Command Injection Through Unsanitized Portfolio Input

Content
View full analysis
Remediation
View remediation
str: value = value.strip() if not re.fullmatch(r"\d{6}", value): raise ValueError("The stock code must contain exactly six digits.") return value code = validate_code(input("Stock code: ")) cost = float(input("Cost: ")) qty = int(input("Quantity: ")) if cost <= 0 or qty <= 0: raise ValueError("Cost and quantity must be positive.") subprocess.run( [ sys.executable, str(PORTFOLIO_SCRIPT), "add", code, "--cost", str(cost), "--qty", str(qty), ], check=True, ) ``` Apply equivalent validation to remove operations. Do not attempt to fix this solely by escaping shell characters; eliminating the shell is more reliable. Handle conversion and subprocess errors explicitly so invalid input cannot produce a partially executed operation. ]]>

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/run_monitor.py:29
Finding

Executable and Script Path Hijacking in Menu Actions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/selector.py:78
Finding

Stock Quote Data Retrieved Over Unencrypted HTTP

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (24)

Tainted flow: 'code' from input (line 35, user input) → os.system (code execution)

Critical
Category
Data Flow
Confidence
100% confidence
Finding

The taint finding is valid: user input from code reaches os.system without sanitization, and cost/qty are also unsafely interpolated into the same shell command. This is classic command injection and can lead to arbitrary command execution, data loss, credential exposure, or host compromise.

Content

Scanner excerpt · scripts/run_monitor.py (reported line 38)May include surrounding context.

python
code = input("股票代码: ")
            cost = input("成本价: ")
            qty = input("数量: ")
            os.system(f"python portfolio.py add {code} --cost {cost} --qty {qty}")
        elif choice == '4':
            code = input("股票代码: ")
            os.system(f"python portfolio.py remove {code}")

Tainted flow: 'code' from input (line 40, user input) → os.system (code execution)

Critical
Category
Data Flow
Confidence
100% confidence
Finding

The user-controlled code value flows directly into os.system in the remove path, making arbitrary command execution possible. Even though this is a local interactive skill, the portfolio-management context does not justify shell access and makes the behavior more dangerous because users may trust and run it with access to personal financial data.

Content

Scanner excerpt · scripts/run_monitor.py (reported line 41)May include surrounding context.

python
os.system(f"python portfolio.py add {code} --cost {cost} --qty {qty}")
        elif choice == '4':
            code = input("股票代码: ")
            os.system(f"python portfolio.py remove {code}")
        elif choice == '5':
            print("再见!")
            break

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

声明强调的是监控/提醒型助手,核心卖点包括“每日自动报告”“止损止盈提醒”“实时盈亏跟踪”。但提供的代码没有任何定时任务、后台运行、消息通知、阈值提醒或事件触发逻辑;它只是一个手动调用的 CLI 脚本,负责本地持仓增删改查,并在执行 analyze 时调用外部分析函数输出当前盈亏与分时分析。因此其实际能力更接近“本地持仓管理与手动分析工具”,与声明中的自动监控和提醒能力存在实质不符。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The description emphasizes automated daily reporting, stop-loss/take-profit reminders, and real-time P/L tracking. However, this code chunk only implements a manual terminal menu that dispatches commands to other scripts. Its observable behavior is primarily a local launcher for reporting, stock selection, and portfolio modification. The included 'run stock selection' feature is undeclared, while key declared capabilities like alerts and real-time tracking are not present in the supplied code. Although 'view position report' partially aligns with the description, the overall behavior shown is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says the skill monitors a user's existing A-share holdings and provides daily position reports, stop-loss/take-profit reminders, and real-time profit/loss tracking. The supplied code does none of that. Instead, it fetches live quote data for a hardcoded list of stocks, computes a selection score, filters high-scoring names, and prints the top candidates. There is no concept of user holdings, cost basis, portfolio state, alert thresholds, scheduled daily reporting, or realized/unrealized P&L. This is a materially different primary purpose, so the description does not accurately represent the code's behavior.

Content

No source excerpt is available for this finding.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · scripts/run_monitor.py (reported line 30)May include surrounding context.

python
if choice == '1':
            print("\n正在生成持仓报告...")
            os.system("python portfolio.py analyze")
        elif choice == '2':
            print("\n正在运行选股...")
            os.system("python selector.py")

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This summary finding is accurate because the skill exposes shell execution for core menu actions and includes unsanitized user input in command strings for add/remove operations. The skill context increases risk: a finance-related assistant may be run by non-technical users on systems containing brokerage exports, credentials, or sensitive reports, so arbitrary command execution is especially severe.

Content

No source excerpt is available for this finding.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · scripts/run_monitor.py (reported line 33)May include surrounding context.

python
os.system("python portfolio.py analyze")
        elif choice == '2':
            print("\n正在运行选股...")
            os.system("python selector.py")
        elif choice == '3':
            code = input("股票代码: ")
            cost = input("成本价: ")

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

This command builds a shell string with untrusted values from input() and passes it to os.system, allowing shell metacharacters in code, cost, or qty to execute arbitrary commands. In an interactive local tool, a user or any upstream automation feeding stdin could trigger arbitrary OS command execution with the privileges of the script.

Content

Scanner excerpt · scripts/run_monitor.py (reported line 38)May include surrounding context.

python
code = input("股票代码: ")
            cost = input("成本价: ")
            qty = input("数量: ")
            os.system(f"python portfolio.py add {code} --cost {cost} --qty {qty}")
        elif choice == '4':
            code = input("股票代码: ")
            os.system(f"python portfolio.py remove {code}")

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

This interpolates the user-supplied stock code directly into a shell command, enabling command injection via crafted input containing shell separators or substitutions. Because deletion is exposed as a simple menu action, exploitation is straightforward for anyone who can provide input to the program.

Content

Scanner excerpt · scripts/run_monitor.py (reported line 41)May include surrounding context.

python
os.system(f"python portfolio.py add {code} --cost {cost} --qty {qty}")
        elif choice == '4':
            code = input("股票代码: ")
            os.system(f"python portfolio.py remove {code}")
        elif choice == '5':
            print("再见!")
            break

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file banner and stated purpose implement a short-term stock picking/scanning tool, which materially differs from the declared skill purpose of portfolio monitoring, reporting, and alerts. This mismatch is dangerous because users may grant trust, install, or run the skill under false expectations, causing unauthorized behavior scope expansion and undermining review controls.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The core logic iterates over a large predefined stock pool, fetches market data, scores securities, and outputs ranked picks rather than monitoring a user's existing holdings. In the context of an investment assistant, this is a significant scope violation that can mislead users and reviewers about what the skill actually does, potentially resulting in unintended trading guidance or use of external data flows not expected from a monitoring tool.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill documentation is entirely written in Chinese and presents the skill as a Chinese A-share assistant without any indication that users may choose another language or locale. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill advertises and demonstrates capabilities that imply shell execution, local file access, and external network access, but it declares no explicit tool scope or permission boundaries. This creates a least-privilege and transparency problem: an agent or reviewer cannot tell what the skill is expected to access, increasing the risk of unintended file modification, arbitrary command execution, or unreviewed outbound requests.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes a portfolio monitoring assistant with daily automatic reports, stop-loss/take-profit reminders, and real-time P&L tracking. In this file, the documented and implemented behavior is limited to local commands for showing, adding, updating, removing, and manually analyzing positions, with no scheduling, alerting, or autonomous reporting logic present.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script calls analyze_stock(code, with_minute=True) for each holding without informing the user that stock codes may be transmitted to an external service or data source. In a portfolio-management context, even stock codes can reveal investment interests and strategy, creating a privacy leak when combined across holdings.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest limits the skill to portfolio monitoring tasks such as daily holding reports, stop-loss/stop-profit reminders, and real-time P/L tracking. This file adds a distinct '运行选股' feature that launches selector.py, which goes beyond monitoring existing holdings into stock screening/selection behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The menu option for deleting a stock immediately runs portfolio.py remove after collecting the code, with no confirmation prompt and no explanatory warning beyond the bare menu label. Because this is a user-data modification/removal action, the file should visibly disclose the effect before executing it.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Natural-language policy violations apply to all file types, including code docstrings and user-facing output. The top-level description and console text force a specific language/locale without indicating user opt-in or a documented region-specific requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file’s natural-language content is entirely in Chinese, including the skill name and usage comments, with no indication that language choice is optional or region-specific. This can violate language/locale policy when a skill implicitly requires a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The script stores portfolio data under a different skill namespace (a-stock-analysis) than the advertised skill (a-stock-portfolio-monitor). This can cause unintended cross-skill data access, confusion about where sensitive holdings data is stored, and accidental reading or overwriting of another skill's local state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code persists user portfolio information to a JSON file under the user's home directory, which affects local user data. While there are success prints after the fact, there is no prior user-facing warning or disclosure in the script header/docstring that add, update, remove, and analyze operations will modify persistent storage.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

All user-facing strings, prompts, and menu text are hard-coded in Chinese, and the script provides no language selection or opt-in. This can violate language/locale policy when a skill is expected to avoid forcing a specific language absent explicit user choice or documented regional scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code makes an external HTTP request to a third-party market data endpoint without user-facing disclosure or consent messaging. While the requested data is public market information and no obvious user secrets are transmitted here, undisclosed network access still reduces transparency and can violate user expectations or platform policy.

Content

No source excerpt is available for this finding.