Back to skill

Security audit

Security App Wealth Advisor

Security checks for vulnerabilities and agentic risk

Overview

This is a non-executing wealth-advisory reference skill, but its examples could lead to unsuitable or misleading financial recommendations if reused without strong human compliance review.

Install only if users understand it as a drafting and design reference, not a production advisor. Do not paste real customer records into it, do not reuse the included code or scripts verbatim, and require qualified compliance and financial-advisor review before any customer-facing use.

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

Warning
Location
SKILL.md:108
Finding
Missing or Invalid Risk Profile Fails Open to Recommendation-Capable Risk Levels<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 108-118 **Vulnerability Type**: Fail-open suitability validation **Risk Level**: Medium ### Complete Code Snippet Non-ASCII source literals are represented below using equivalent Unicode escapes. ```python risk_level_map = { "\u4fdd\u5b88\u578b": ["R1", "R2"], "\u7a33\u5065\u578b": ["R1", "R2", "R3"], "\u5e73\u8861\u578b": ["R2", "R3", "R4"], "\u6210\u957f\u578b": ["R3", "R4", "R5"], "\u6fc0\u8fdb\u578b": ["R4", "R5"] } allowed_risk = risk_level_map.get( customer_profile.get("risk_preference", "\u7a33\u5065\u578b"), ["R2", "R3"] ) ``` ### Technical Analysis The product-matching example defaults a missing `risk_preference` to a moderate profile that permits R1 through R3 products. If an unrecognized value is supplied, the second fallback permits R2 and R3 products. This is a fail-open design. The rest of the document states that a valid and current risk assessment is required before making recommendations, but the illustrated implementation does not validate the presence, provenance, validity period, or recognized value of that assessment. Because malformed or incomplete input still produces an eligible-risk list, downstream matching can return financial products despite the absence of a confirmed suitability classification. ### Attack Path 1. A caller submits a customer profile without `risk_preference`, or supplies an unsupported value. 2. The code silently selects a default risk profile or the `["R2", "R3"]` fallback. 3. Products in those risk categories pass the risk filter. 4. The function scores and returns them as recommendations. 5. If the illustrative logic is adopted without the required human controls, the recommendations may be displayed to a customer without a valid suitability determination. ### Impact Assessment No operating-system privileges, credentials, or application permissions can be obtained through this issue. The affected scope ...[truncated 446 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Adopt fail-closed validation before any product filtering or scoring: 1. Require `risk_preference` to be present and mapped to an explicitly supported value. 2. Reject missing, unknown, malformed, expired, or unverified assessments. 3. Validate the assessment timestamp, version, customer identity binding, and originating compliant channel. 4. Return a structured validation error rather than a recommendation list. 5. Keep suitability validation separate from ranking logic so scoring cannot override eligibility. 6. Add tests for missing values, unknown values, expired assessments, forged classifications, and boundary risk levels. Example hardened logic: ```python risk_preference = customer_profile.get("risk_preference") assessment_valid = customer_profile.get("risk_assessment_valid", False) if not assessment_valid: raise ValueError("A valid and current risk assessment is required.") if risk_preference not in risk_level_map: raise ValueError("The customer risk classification is missing or unsupported.") allowed_risk = risk_level_map[risk_preference] ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:151
Finding
Products Above the Customer's Available Funds Remain Recommendable<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 151-166 **Vulnerability Type**: Missing hard eligibility filter **Risk Level**: Medium ### Complete Code Snippet ```python def _calculate_match_score(self, customer: dict, product: dict) -> float: """Calculate the matching score.""" score = 100 preferred_term = customer.get("preferred_term", 365) product_term = product.get("term_days", 365) term_diff = abs(preferred_term - product_term) / 365 score -= term_diff * 10 if product.get("min_amount", 0) > customer.get("available_fund", 0): score -= 30 expected = customer.get("expected_return", 0.05) actual = product.get("expected_return", 0) if actual >= expected: score += 10 else: score -= abs(actual - expected) * 100 return max(0, min(100, score)) ``` ### Technical Analysis The minimum purchase amount is treated as a soft ranking factor rather than a hard eligibility condition. When `min_amount` exceeds `available_fund`, the score is reduced by only 30 points. The product remains in the result set and can still obtain a relatively high score from its initial score, term alignment, and expected-return bonus. The outer matching function sorts all retained products by score and does not remove financially infeasible products. Missing fields also fail open: a missing product minimum defaults to zero, while a missing customer available-fund value defaults to zero without generating an input-validation error. ### Attack Path 1. A product is supplied with a minimum purchase amount greater than the customer's available funds. 2. The product passes the risk and expected-return filters. 3. The scoring function applies only a 30-point reduction. 4. Favorable term and expected-return values preserve or increase its score. 5. The product remains in the sorted recommendation list and may be shown to the customer. 6. The customer may be encouraged to ...[truncated 641 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Move financial eligibility checks ahead of scoring and fail closed when required values are absent: 1. Require validated numeric values for `available_fund` and `min_amount`. 2. Reject negative values, unsupported currencies, NaN values, and inconsistent units. 3. Remove products whose minimum purchase amount exceeds the customer's available funds. 4. Account for fees, reserved balances, currency conversion, and product-specific purchase increments. 5. Retain scoring only for products that have passed all hard eligibility checks. 6. Add unit tests proving that unaffordable products can never appear in the returned list. Example hardened filter: ```python available_fund = customer_profile.get("available_fund") if not isinstance(available_fund, (int, float)) or available_fund < 0: raise ValueError("A valid available-fund amount is required.") for product in available_products: min_amount = product.get("min_amount") if not isinstance(min_amount, (int, float)) or min_amount < 0: continue if min_amount > available_fund: continue # Apply the remaining eligibility checks before scoring. ``` ]]>

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:235
Finding
Customer-Facing Template Uses Principal-Preservation and Stable-Return Implications<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 235-249 **Vulnerability Type**: Misleading financial communication template **Risk Level**: Low ### Complete Code Snippet The original source literals are represented using equivalent Unicode escapes. The vulnerable statements respectively describe principal-preservation suitability, stable returns with low volatility, and steady asset appreciation. ```text \u7279\u70b9\uff1a\u5b89\u5168\u7a33\u5065\uff0c\u9002\u5408\u4fdd\u672c\u9700\u6c42 \u7279\u70b9\uff1a\u6536\u76ca\u7a33\u5065\uff0c\u6ce2\u52a8\u8f83\u5c0f \u540c\u65f6\u5b9e\u73b0\u8d44\u4ea7\u7684\u7a33\u5065\u589e\u503c\u3002 ``` ### Technical Analysis The supplied customer-facing allocation template characterizes an allocation as suitable for principal-preservation needs, describes returns as stable, and states that the allocation can achieve steady asset appreciation. These statements can imply principal protection or dependable investment performance. They conflict with the same document's compliance section, which prohibits principal-guarantee and guaranteed-return wording. The template groups products with materially different legal and risk characteristics. Without product-specific qualification, customers may incorrectly infer that all listed components offer deposit-like principal protection or predictable returns. ### Attack Path 1. A user asks the skill to produce an asset-allocation explanation. 2. The agent reuses or adapts the embedded template. 3. The resulting communication includes principal-preservation or stable-growth implications. 4. Human review is omitted, ineffective, or treats the provided template as preapproved. 5. The wording is delivered to a customer and may be interpreted as a guarantee or as minimizing investment risk. ### Impact Assessment No technical privileges or system access can be gained. The affected scope is customer communication and financial-sales compliance. Potential impact ...[truncated 367 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove wording that suggests principal protection, stable returns, or assured appreciation. 2. Clearly distinguish deposits from non-deposit investment products. 3. State whether each product is principal-protected and identify its material risks. 4. Use product-specific disclosures rather than generic descriptions such as “safe” or “stable.” 5. Require comparison benchmarks, complete performance periods, and risk indicators whenever historical performance is presented. 6. Make human compliance approval a mandatory workflow control rather than relying only on a disclaimer. 7. Add an automated phrase checker that blocks guarantee-like wording before customer delivery. A safer English formulation would be: ```text This allocation is an illustrative discussion framework rather than a personalized recommendation. Investment products may experience losses and are not equivalent to deposits. Actual performance and liquidity depend on the terms and operation of each product. Review the product documentation, risk disclosures, and your current suitability assessment before deciding. ``` ]]>
Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger list is broad enough to activate on generic banking, customer service, or product-support requests rather than only wealth-advisory scenarios. In this context, ambiguous invocation can cause the skill to engage inappropriately and generate advisory-style content where a narrower support or compliance workflow would be safer, increasing the chance of unsuitable or over-personalized financial guidance.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The skill includes a script section framed as compliant guidance, but the same section contains language such as '保本需求', '安全稳健', and '稳健增值' that can be interpreted as implicit capital-preservation or return assurances in a regulated wealth-advice context. Because this skill is designed for bank wealth advisory use, contradictory examples inside a purported compliance template materially increase the risk that staff or downstream systems reuse non-compliant phrasing with customers.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The trigger section labels Chinese keywords as "优先" (preferred/priority), which suggests a locale or language preference baked into activation behavior. Although the document is bilingual, it does not explicitly state that users may choose their language, so this may conflict with a policy against forcing a specific language or locale without opt-in.

Static analysis

No suspicious patterns detected.