Back to skill

Security audit

Fund Advisor

Security checks for vulnerabilities and agentic risk

Overview

This fund-advisor skill is not malicious, but it stores and shares sensitive investment information with weakly scoped controls that should be reviewed before installation.

Review this skill before installing in any real financial or multi-user environment. Require explicit opt-in before saving profiles or diaries, uploading reports to S3, or sending Feishu messages, and replace /tmp plaintext storage with a protected per-user store, strong path validation, encryption, retention limits, and deletion controls.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
references/data-storage.md:183
Finding

User-Controlled Path Construction Enables Path Traversal and Cross-User File Access

Content
View full analysis

Vulnerability Details

File Location: references/data-storage.md:183, references/data-storage.md:213, references/data-storage.md:261, references/data-storage.md:317, references/data-storage.md:381, and references/data-storage.md:696-705
Vulnerability Type: Path traversal and broken access control
Risk Level: High

Vulnerable Code

python
file_path = os.path.join(USER_PROFILES_DIR, f"{user_id}.json")
python
file_path = os.path.join(SIP_PLANS_DIR, f"{user_id}_{plan_id}.json")
python
file_path = os.path.join(INVESTMENT_DIARY_DIR, f"{user_id}_diary_{diary_id}.json")
python
def check_file_access(file_path: str, user_id: str) -> bool:
    """Check file access permissions."""
    # The filename should contain user_id
    if user_id not in file_path:
        return False
    
    # Check whether the file exists
    if not os.path.exists(file_path):
        return False
    
    return True

Technical Analysis

The documented storage functions interpolate caller-controlled user_id and plan_id values directly into filesystem paths. The code does not reject absolute paths, directory separators, .. components, control characters, or other unsafe filename content.

os.path.join() does not enforce containment. A crafted identifier can introduce traversal components, while an absolute path component can cause preceding path components to be discarded in applicable constructions. The resulting path is then passed to generic JSON read or write functions.

The proposed check_file_access() function does not provide effective authorization. It only checks whether the textual user_id appears somewhere in the path and whether the file exists. It does not:

  • Canonicalize the path.
  • Verify that the resolved path remains under the expected storage root.
  • Establish that the authenticated caller owns the requested record.
  • Prevent one user id ...[truncated 1545 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not use caller-provided identifiers directly as filenames. Map authenticated account identifiers to server-generated opaque identifiers such as UUIDs.

  2. Apply a strict allowlist to every path component, for example ^[A-Za-z0-9_-]{1,64}$.

  3. Resolve and validate every path before access:

    python
    from pathlib import Path
    
    ROOT = Path("/var/lib/fund-advisor/user_profiles").resolve()
    
    def safe_profile_path(user_id: str) -> Path:
        if not re.fullmatch(r"[A-Za-z0-9_-]{1,64}", user_id):
            raise ValueError("Invalid user identifier")
    
        candidate = (ROOT / f"{user_id}.json").resolve()
        if ROOT not in candidate.parents:
            raise PermissionError("Path escapes the storage root")
        return candidate
    
  4. Derive the effective user identity from authenticated session context rather than accepting arbitrary user_id values from Agent tool arguments.

  5. Enforce record ownership for every create, read, update, and delete operation.

  6. Reject symbolic links or use safe descriptor-based file operations where the platform supports them.

  7. Add tests for ../, absolute paths, mixed separators, symbolic links, Unicode separator variants, and identifiers that are substrings of other identifiers.

  8. Remove the substring-based check_file_access() implementation and replace it with canonical containment plus authenticated ownership validation.

T09 · Insecure Skill Coding Practices

Warning
Location
references/data-storage.md:136
Finding

Sensitive Financial Data Is Stored as Plaintext in Shared Temporary Directories

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:179-194 and references/data-storage.md:136-154, references/data-storage.md:166-195, references/data-storage.md:251-280, references/data-storage.md:367-397
Vulnerability Type: Plaintext sensitive-data storage and unsafe temporary-file usage
Risk Level: Medium

Vulnerable Code

python
DATA_DIR = "/tmp"
USER_PROFILES_DIR = os.path.join(DATA_DIR, "user_profiles")
SIP_PLANS_DIR = os.path.join(DATA_DIR, "sip_plans")
INVESTMENT_DIARY_DIR = os.path.join(DATA_DIR, "investment_diary")
python
def _ensure_dir(dir_path: str):
    if not os.path.exists(dir_path):
        os.makedirs(dir_path, exist_ok=True)

def _save_json(file_path: str, data: dict):
    _ensure_dir(os.path.dirname(file_path))
    with open(file_path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
python
profile = {
    "user_id": user_id,
    "risk_level": risk_level,
    "investment_period": investment_period,
    "available_funds": available_funds,
    "expected_return": expected_return,
    "updated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}

_save_json(file_path, profile)

Technical Analysis

The proposed storage layer writes investor profiles, available funds, expected returns, recurring investment plans, execution history, and diary content to plaintext JSON files beneath /tmp.

/tmp is commonly shared by multiple users and processes. The code does not explicitly set restrictive directory or file permissions, so effective access depends on the process umask and host configuration. Predictable directory and filename patterns further facilitate local discovery.

Although the document later includes an isolated Fernet encryption example, encryption is not integrated into _save_json() or any of the shown financial-data tools. The encryption example also generates a new key at process s ...[truncated 1770 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace /tmp with a dedicated application data directory outside shared temporary storage.
  2. Create the application directory with mode 0700 and data files with mode 0600, independent of the ambient umask.
  3. Separate each authenticated tenant into a protected namespace and enforce ownership on all operations.
  4. Encrypt sensitive fields at rest using a stable key retrieved from a managed key-management or secret-management service.
  5. Do not generate a new encryption key at every process start. Implement key identifiers, rotation, and migration procedures.
  6. Use atomic writes: create a new file securely in the protected directory, flush and synchronize it, set permissions, and atomically replace the destination.
  7. Avoid predictable filenames where they are not required; use server-generated record identifiers.
  8. Establish explicit retention periods and secure deletion procedures for profiles, plans, notifications, and diaries.
  9. Do not include full sensitive records or local filesystem paths in tool responses or logs.
  10. Add deployment checks that fail securely when directory ownership or permissions are broader than intended.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:9
Finding

Unpinned and Unverified Third-Party Dependencies Create Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:9, SKILL.md:159-165, references/skill-integration.md:39-43, references/skill-integration.md:144-148, references/skill-integration.md:262-266, and references/skill-integration.md:372-376
Vulnerability Type: Mutable dependency resolution without integrity verification
Risk Level: Medium

Vulnerable Code

yaml
requirements: ["coze-coding-dev-sdk>=0.5.11", "langchain>=1.0", "langgraph>=1.0"]
bash
# Core dependencies
coze-coding-dev-sdk>=0.5.11
langchain>=1.0
langgraph>=1.0

# Optional dependency
requests
bash
uv add coze-coding-dev-sdk
bash
uv add requests

Technical Analysis

The dependency guidance uses lower-bound constraints or no version constraint. It does not provide a committed lockfile, package hashes, trusted-index restrictions, signature verification, or documented provenance controls.

Therefore, two installations performed at different times may resolve to materially different dependency trees. Future releases are implicitly trusted without review, including transitive dependencies introduced by those releases.

Python packages and their build backends may execute code during build or installation. A compromised upstream release, compromised package account, malicious transitive dependency, or dependency-confusion event could consequently execute code with the installer or Agent process privileges.

The audit found no evidence that the named packages are currently malicious. The vulnerability is the project's unsafe and non-reproducible dependency acquisition policy, not a claim that a specific dependency contains malicious code.

Attack Path

  1. A user follows the documented uv add or dependency installation instructions.
  2. The resolver queries configured package indexes and selects the newest version satisfying the broad constraint.
  3. An upstream account, package release, pa ...[truncated 955 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to an exact reviewed version.
  2. Generate and commit a reproducible lockfile containing the full transitive dependency graph.
  3. Require artifact hashes and reject packages whose hashes do not match the reviewed lock data.
  4. Restrict package resolution to explicitly approved HTTPS indexes; disable unintended extra indexes.
  5. Review package ownership, release history, source repository, signatures, and build configuration before approval.
  6. Run software composition analysis and vulnerability scanning in continuous integration.
  7. Perform dependency updates through reviewed pull requests rather than resolving latest versions during deployment.
  8. Build dependencies in an isolated, unprivileged environment without production credentials.
  9. Produce and retain a software bill of materials for each release.
  10. Ensure runtime images install only locked production dependencies and do not contain package-manager credentials.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (25)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file states the skill uses web-search, document-generation, feishu-message, filesystem, and S3 storage, which can affect user data, privacy, or system integrity. The description does not include any warning or disclosure about storing user data, generating files, or sending information to external services.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The top-level description and the entire skill documentation are written as a Chinese-only fund advisory experience, with no indication that users may choose another language or that the skill is intentionally restricted to a China-specific locale for compliance reasons. Under the policy, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill documents storage of user profiles, investment diaries, notification settings, and cloud upload of reports, but does not clearly warn users about what data is retained, where it is sent, how long it is stored, or what third parties receive it. In a financial-advisory workflow, this creates meaningful privacy and confidentiality risk because sensitive personal and portfolio information may be persisted or transmitted unexpectedly.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill claims it does not recommend specific fund products, yet the examples and tooling clearly support specific fund lookup and recommendation-adjacent behavior. This mismatch can mislead users, reviewers, or compliance controls about the actual advisory scope, increasing regulatory, trust, and suitability risk in a financial context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation instructs the agent to create investment diary entries from free-form user text without warning that this content will be stored. In a financial-advisory context, diary entries may contain sensitive financial views, plans, or personal data, so silent persistence can create privacy, consent, and data-retention risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The examples describe setting market alerts and linking Feishu notifications without warning that data may be transmitted to an external messaging platform. In this skill’s financial context, alerts can reveal investment interests, holdings, or behavior patterns, making undisclosed third-party sharing a real privacy and information-disclosure risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The file consistently defines the skill behavior and examples in Chinese, including prompt content and output expectations, but does not indicate that users may choose another language. This can amount to a language/locale policy violation when a skill effectively forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The summarization example sends prior conversation content into a summarization prompt and the logging section records tool parameters and result snippets, but the document provides no sensitivity filtering, redaction, or retention limits. For a fund advisor, conversations may contain personal financial details, account context, or contact data, so semantic summaries and debug logs can preserve sensitive information beyond the active session and expand the exposure surface.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document recommends persisting user preferences to /tmp/user_profiles/{user_id}.json without any discussion of consent, data minimization, retention, access controls, or sensitivity classification. In a financial advisory agent, user preferences can reveal investment goals, risk tolerance, assets, and other personal financial data, so writing them to disk by default increases privacy and compliance risk if the host is shared, logs are exposed, or files are retained longer than expected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The design sends generated portfolio reports containing sensitive financial profile data to S3 and returns downloadable links, but the document does not define consent, data-classification, retention, bucket policy, encryption, or link-sharing safeguards. In a fund-advisor context, this increases privacy and compliance risk because investor suitability data and financial preferences are sensitive and may be exposed through misconfiguration or broad link access.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The encryption example generates a new Fernet key at startup, so previously encrypted persistent data cannot be reliably decrypted after restart or redeploy. This creates a false sense of protection and can lead to data loss or insecure workarounds such as disabling encryption or storing plaintext copies.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documented access-control check is ineffective because it authorizes based only on whether the user_id string appears anywhere in the file path. An attacker who can influence file names or paths can bypass this check with crafted values, and the function does not bind access to an authenticated identity, canonical path validation, or per-user directory boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The document-generation guidance explicitly states generated files are uploaded to S3 and exposed via 24-hour presigned download URLs, but it does not instruct callers to obtain user consent, minimize sensitive content, or warn users that report data leaves the local/runtime boundary. In a financial advisory skill, reports can contain portfolio, risk profile, and personal investment data, so silent external storage materially increases privacy and data-leakage risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The Feishu messaging integration shows sending report content and alerts to a webhook without warning that message bodies and embedded links are transmitted to an external service. Because this skill operates in an investment context, messages may include sensitive financial recommendations, portfolio status, or downloadable report URLs, which could expose confidential user data to unintended recipients or third-party systems.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This code performs an outbound HTTP POST to a Feishu webhook, which is an intentional external transmission path. While the transmission itself is expected functionality, it becomes security-relevant because the example encourages sending arbitrary text notifications in a finance workflow without guardrails on sensitive content, recipient validation, or user consent.

Content

Scanner excerpt · references/skill-integration.md (reported line 404)May include surrounding context.

md
"content": {"text": text}
    }
    
    response = requests.post(webhook_url, json=payload)
    return response.json()

# 发送

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

This outbound POST sends rich-text content, including hyperlinks, to an external Feishu endpoint. In the context of a fund-advisor skill, rich messages can carry sensitive investment information or direct access links, making the transmission path a real data-exposure risk if webhook destinations are misconfigured or messages are over-shared.

Content

Scanner excerpt · references/skill-integration.md (reported line 433)May include surrounding context.

} }

text
response = requests.post(webhook_url, json=payload)
return response.json()
text

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This external POST sends an interactive card message to Feishu, potentially including actionable content and URLs. The risk is not the API call alone but the lack of safeguards around transmitting financial guidance and links to an external messaging platform, which can increase accidental disclosure or misuse if recipients or webhook scopes are broader than intended.

Content

Scanner excerpt · references/skill-integration.md (reported line 466)May include surrounding context.

md
}
    }
    
    response = requests.post(webhook_url, json=payload)
    return response.json()

# 示例

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The combined workflow generates a report, uploads it externally, and then transmits the resulting download URL through Feishu, yet provides no warning or consent step for either disclosure. This chaining amplifies the risk: anyone with access to the chat destination or leaked webhook output may retrieve a sensitive investment report during the presigned URL validity window.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The documented tool sends arbitrary text to an externally retrieved Feishu webhook URL, which creates a data exfiltration channel if sensitive user or portfolio data is passed into the function. In an investment-advisor skill, this is more dangerous because the content may include personal financial information, recommendations, or internal analysis, and the example shows no content classification, destination allowlisting, or consent checks before transmission.

Content

Scanner excerpt · references/tool-development.md (reported line 253)May include surrounding context.

md
"content": {"text": text}
        }
        
        response = requests.post(webhook_url, json=payload, timeout=10)
        
        if response.status_code == 200:
            return "✅ 消息发送成功"

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language documentation and usage example are written for Chinese-language use, but the file does not state that the skill is region-specific or offer users an alternative language/locale option. Under the policy, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

All headings, instructions, and example interactions are presented only in Chinese, which can amount to an implicit fixed-language experience if this file is used as the skill's user-facing guidance. There is no note offering alternative language support or clarifying that Chinese is an optional, locale-specific version.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file includes a workflow and sample prompts for generating a PDF report and returning a download link, which affects user data by creating an output artifact. The surrounding documentation does not include any warning or disclosure about report generation, storage, or where the downloadable file is hosted.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest describes a fund advisory skill focused on fund data, portfolio allocation, risk assessment, market monitoring, investment education, and four integrations. This usage file additionally presents creating investment diaries and analyzing user sentiment/market views as core agent behavior, which is not clearly covered by the stated purpose and suggests broader personal-record features.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The best-practices section advises users to '查询历史对话' as if conversation-history retrieval is a supported capability. The manifest does not mention chat-history search or retrieval, so the documented behavior expands the apparent scope beyond the declared fund-advisory and listed integrations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

L147-L149 的自然语言说明明确规定 title 参数“必须使用英文”。这构成了语言/locale 约束,但文档没有提供用户可选项,也没有说明该限制是出于区域性或合规性要求,因此符合语言策略违规的判定条件。

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.