Back to skill

Security audit

Stock Watcher THS

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stock-watchlist purpose, but it has an unsafe uninstall script that can recursively delete an arbitrary environment-selected directory and ships reusable API authorization material.

Review before installing. Use this only in an isolated environment or after fixing uninstall.sh to delete only the skill-owned watchlist file, and avoid setting STOCK_WATCHER_DATA_DIR to any valuable directory. The maintainer should also replace or remove the embedded API authorization header and pin dependencies.

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
scripts/uninstall.sh:6
Finding

Unrestricted Environment Variable Enables Arbitrary Recursive Directory Deletion

Content
View full analysis

Vulnerability Details

File Location: scripts/uninstall.sh:6-10
Vulnerability Type: Unsafe recursive deletion using an unvalidated, user-controlled path
Risk Level: High

Vulnerable Code

bash
WATCHLIST_DIR="${STOCK_WATCHER_DATA_DIR:-$SKILL_DIR/data}"
WATCHLIST_DIR="${WATCHLIST_DIR/#\~/$HOME}"

if [ -d "$WATCHLIST_DIR" ]; then
    rm -rf "$WATCHLIST_DIR"
fi

Technical Analysis

The STOCK_WATCHER_DATA_DIR environment variable directly determines the target passed to rm -rf. Although quoting prevents shell-word splitting and command injection, the script does not canonicalize the path, restrict it to a dedicated application directory, verify an ownership marker, or reject dangerous targets such as /, $HOME, or unrelated directories.

Supporting a custom data location is consistent with the Skill's declared functionality, but recursively deleting the entire configured directory exceeds the minimum privilege needed to remove the watchlist. The script only needs to remove the Skill-owned watchlist.txt file and, at most, remove the containing directory if it is known to have been created exclusively by this Skill and is empty.

Attack Path

  1. An attacker, automation wrapper, or unsafe execution environment controls STOCK_WATCHER_DATA_DIR.
  2. The variable is set to an existing valuable directory, for example:
    bash
    STOCK_WATCHER_DATA_DIR="$HOME" bash scripts/uninstall.sh
    
  3. The script confirms only that the selected path is a directory.
  4. rm -rf "$WATCHLIST_DIR" recursively deletes that directory and all accessible contents.
  5. If the script is run with elevated privileges, the deletion scope expands to files accessible to that privileged account.

Impact Assessment

Exploitation can destroy arbitrary directories writable by the account running the script. Under a normal user account, this could include personal files, configuration, credentials, and ...[truncated 302 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove only the specific Skill-owned file:
    bash
    WATCHLIST_FILE="$WATCHLIST_DIR/watchlist.txt"
    rm -f -- "$WATCHLIST_FILE"
    rmdir -- "$WATCHLIST_DIR" 2>/dev/null || true
    
  • Canonicalize and validate the directory before any destructive operation.
  • Explicitly reject empty paths, /, $HOME, the project root, and other protected locations.
  • Place a unique ownership marker in directories created by the Skill and require that marker before deleting the directory.
  • Never recursively delete a custom directory merely because it was supplied through an environment variable.
  • Require explicit user confirmation before removing non-default data locations.
  • Do not recommend or require elevated privileges for uninstallation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/summarize_performance.py:23
Finding

Reusable API Authorization Token Embedded in Source Code

Content
View full analysis

Vulnerability Details

File Location: scripts/summarize_performance.py:23-30
Vulnerability Type: Hardcoded authorization material
Risk Level: Medium

Vulnerable Code

python
"x-auth-appname": "AINVEST",
"x-auth-progid": "7047",
"x-auth-type": "ths",
"x-auth-version": "1.0",
"x-fuyao-auth": (
    "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9."
    "eyJhdXRob3JpemVyX25hbWVzcGFjZSI6ImNvbW1vbi1ocS1hZ2dyIiwibGljZW5zZWVfdHlwZSI6IkZST05UX0FQUCIsImxpY2Vuc2VlX25hbWVzcGFjZSI6Imh4a2xpbmUtTkVXU19hcHBOZXdzRmxvd0hvbWVfUGFnZSJ9."
    "ldrvWTheNnGOa_rH_buA6OoUpLtW2bhcdr3fABrGHbk"
),

Technical Analysis

The source contains a signed JWT-like value that is transmitted through the x-fuyao-auth request header to an unofficial 10jqka endpoint. It is not shown to be a user's personal credential, and the decoded payload appears associated with a front-end application namespace. Nevertheless, it is reusable authorization material embedded in a distributable repository.

Anyone with access to the source can extract and replay the value independently of the Skill. Its authorization scope, expiry, rotation process, licensing terms, and intended audience are not controlled by this project. Embedding it also prevents secure revocation or per-user accountability.

The actual quote request sends only stock codes, market identifiers, and requested quote fields. No browser cookies, login tokens, or unrelated local data are collected. Therefore, the network behavior is aligned with quote retrieval, but shipping copied authorization material is not a safe way to obtain that access.

Attack Path

  1. An attacker downloads or reads the Skill source.
  2. The attacker extracts the x-fuyao-auth value and associated application headers.
  3. The attacker replays those headers in independent requests to the corresponding API.
  4. Requests are attributed to the shared embedded authorization context rather than an individually provi ...[truncated 649 chars]
Remediation
View remediation

Remediation Suggestions

  • Use an officially documented public quote API that does not require copied front-end authorization material.
  • If authorization is legitimately required, provision credentials through the provider's supported process.
  • Load credentials from a dedicated secret manager or protected runtime configuration rather than committing them to source control.
  • Ensure credentials are scoped to the minimum required quote-read permissions and support expiration and rotation.
  • Revoke or rotate the exposed value if the project controls it.
  • Document the remote service, data sent, authentication requirements, and applicable usage terms.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Dependencies Permit Installation of Unreviewed Future Releases

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-2
Vulnerability Type: Non-reproducible dependency resolution without integrity verification
Risk Level: Medium

Vulnerable Code

text
requests>=2.31.0
beautifulsoup4>=4.12.0

The documented installation command in README.md:16 and SKILL.md:37 is:

bash
python3 -m pip install -r requirements.txt

Technical Analysis

Both dependencies use unrestricted lower bounds. A future installation can therefore resolve to any newer release accepted by the package resolver, even though that release was not present during the audit. No lock file or package hashes are provided to establish a reproducible and integrity-checked dependency set.

The package names correspond to established projects, so there is no evidence of typosquatting or dependency confusion in the current names. The risk arises from trusting mutable future releases and the configured package index without version or artifact verification.

Python package installation may execute build backend logic, and compromised dependencies can also execute when imported by the Skill. Consequently, dependency installation and runtime behavior can change after review.

Attack Path

  1. A user follows the documented installation command.
  2. pip queries the configured package index and selects any releases satisfying the open-ended lower bounds.
  3. A compromised, malicious, or unexpectedly incompatible future release is selected.
  4. Package-controlled behavior may execute during build or installation, or later when requests or bs4 is imported.
  5. That code runs with the filesystem, network, and process privileges of the user performing the installation or running the Skill.

Impact Assessment

A compromised dependency could access or modify files available to the invoking user, make arbitrary network requests, steal process-accessible secrets, or execute command ...[truncated 348 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin dependencies to exact versions that have been reviewed and tested:
    text
    requests==<reviewed-version>
    beautifulsoup4==<reviewed-version>
    
  • Generate and commit a lock file containing all transitive dependencies.
  • Add hashes for every permitted distribution and install with:
    bash
    python3 -m pip install --require-hashes -r requirements.txt
    
  • Use a controlled and trusted package index.
  • Install dependencies in an isolated virtual environment rather than into a global or privileged Python environment.
  • Establish a regular dependency-update process that includes vulnerability scanning, review, testing, and regenerated hashes.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill requests or implies capabilities to read environment variables, read and write local files, and access the network, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity: a host agent may grant broader access than users expect, and the skill can persist local data and fetch remote content without clear least-privilege boundaries.

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 · scripts/summarize_performance.py (reported line 65)May include surrounding context.

python
}

    try:
        response = requests.post(THS_SNAPSHOT_URL, headers=THS_HEADERS, json=payload, timeout=10)
        response.raise_for_status()
        result = response.json()
        if result.get("status_code") != 0:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The uninstall script recursively deletes the directory specified by STOCK_WATCHER_DATA_DIR or the default data path without any validation, safety guardrails, or confirmation prompt. Because the path is influenced by an environment variable and rm -rf is used, a mistaken or maliciously set value could cause unintended deletion of arbitrary local directories.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The description explicitly constrains the skill to 'Chinese A-share' stocks, which is a locale-specific limitation expressed in natural language. The file does not indicate that this is optional or user-selectable, and there is no stated justification such as region-specific compliance requirements.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is not pinned to an exact version, so builds are not reproducible and may silently resolve to different releases over time. That increases supply-chain risk and makes it harder to ensure the installed version is free of known vulnerabilities or breaking changes.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
beautifulsoup4>=4.12.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The manifest includes requests without an exact pinned version, and the package has multiple historical advisories. Because version selection is unconstrained above 2.31.0, it is not possible to verify from this file alone whether deployments will avoid affected releases, creating uncertainty and potential exposure.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

beautifulsoup4 is specified with a lower-bound only, which allows any newer version to be installed. This weakens reproducibility and can introduce unexpected vulnerable or incompatible releases into the environment.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
beautifulsoup4>=4.12.0

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The request payload hard-codes lang to zh_cn, which enforces a specific locale. Under the policy, locale constraints should either be user-selectable or clearly documented as justified; neither is visible in this file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.