Back to skill

Security audit

stock-analysis-zh

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but an undocumented endpoint override can send the AISA API key and analysis request to a non-AISA server.

Review before installing. Use it only in a trusted, minimal environment, keep AISA_BASE_URL unset unless you intentionally point it at a trusted compatible endpoint, and assume ticker symbols and generated analysis prompts are sent to an external AISA-compatible API. Consider pinning dependencies before routine use.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/analyze_stock.py:118
Finding

API Credential Exposure Through an Unrestricted Base URL Override

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_stock.py, lines 118–124 and 159–166
Vulnerability Type: Unrestricted network destination for authenticated API requests
Risk Level: High

Vulnerable Code

python
def get_client() -> OpenAI:
    api_key = os.environ.get("AISA_API_KEY")
    if not api_key:
        print("❌ Error: AISA_API_KEY environment variable is not set.", file=sys.stderr)
        print("   Set it with: export AISA_API_KEY=your_key_here", file=sys.stderr)
        sys.exit(1)
    base_url = os.environ.get("AISA_BASE_URL", "https://api.aisa.one/v1")
    return OpenAI(api_key=api_key, base_url=base_url)

The resulting client is subsequently used for an authenticated request:

python
try:
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": prompt},
        ],
        temperature=0.1,
    )

Technical Analysis

The Skill legitimately needs to send the requested ticker symbols and analysis prompt to the declared AISA API. Sending AISA_API_KEY to the default https://api.aisa.one/v1 service is therefore consistent with its documented functionality.

However, the destination is controlled by the undeclared AISA_BASE_URL environment variable without scheme or hostname validation. The OpenAI client uses AISA_API_KEY to authenticate requests sent through this configured base URL. If the variable points to an attacker-controlled API-compatible endpoint, the client can disclose the API credential and request contents to that endpoint.

This behavior exceeds the minimum privileges required by the declared functionality because the Skill only documents use of the AISA service and does not require unrestricted authenticated communication with arbitrary hosts. The code does not explicitly place the key in the model prompt o ...[truncated 1651 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the AISA_BASE_URL override if custom endpoints are not an intended and documented feature:

    python
    return OpenAI(
        api_key=api_key,
        base_url="https://api.aisa.one/v1",
    )
    
  2. If endpoint customization is required, declare it in SKILL.md and validate it before constructing the client:

    • Require the https scheme.
    • Maintain an explicit allowlist of trusted hostnames.
    • Reject embedded user information and credentials.
    • Reject unexpected ports, IP literals, and malformed URLs.
    • Ensure redirects cannot transfer authenticated requests to an untrusted host.
  3. Use separate, narrowly scoped credentials for custom endpoints rather than forwarding the AISA production credential.

  4. Apply server-side restrictions to the key where supported, including quota limits, endpoint restrictions, expiration, and key rotation.

  5. Clearly disclose that ticker symbols and prompts are sent to an external service, while ensuring that unrelated environment variables, files, and local credentials are never included.

T08 · Insecure Dependencies

Warning
Location
scripts/analyze_stock.py:3
Finding

Mutable Runtime Dependency Without an Exact Version or Integrity Lock

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_stock.py, lines 3–7
Vulnerability Type: Unpinned third-party runtime dependency
Risk Level: Medium

Vulnerable Code

python
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "openai>=1.0.0",
# ]
# ///

Technical Analysis

The PEP 723 dependency declaration allows any current or future openai package version satisfying >=1.0.0. No lockfile, exact version, package hash, or verified package source is included in the project.

When the script is executed through a compatible dependency-resolving tool, such as the uv run command shown in its usage documentation, dependency resolution may download a different package release from the one originally reviewed. This makes the effective runtime supply chain mutable after the Skill audit.

The code does not identify a typosquatted package or a presently malicious dependency. The security concern is that an upstream compromise, malicious satisfying release, or compromised package source could cause unreviewed code to be installed and imported with the user's privileges.

There is also a documentation mismatch: SKILL.md recommends direct execution with python3, while the script header examples use uv run. The direct command depends on openai already being installed and does not establish a reproducible, verified dependency installation process.

Attack Path

  1. An attacker compromises the configured Python package source or causes a malicious or compromised openai release satisfying >=1.0.0 to be selected.
  2. A user invokes the script through a PEP 723-aware runner that resolves the declared dependency.
  3. The runner retrieves and installs the selected dependency without a project-provided hash or lockfile restricting it to the audited artifact.
  4. Malicious package installation or import-time code executes in the context of the user running the Skill.
  5. Th ...[truncated 898 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin the dependency to an exact version that has been reviewed and tested:

    python
    # dependencies = [
    #     "openai==<audited-version>",
    # ]
    
  2. Commit a lockfile containing cryptographic hashes for all direct and transitive dependencies.

  3. Configure installation to use a trusted, authenticated package index and disable unapproved supplemental indexes to reduce dependency-confusion exposure.

  4. Regularly update pinned dependencies through a controlled review process that includes vulnerability scanning, changelog inspection, and regression testing.

  5. Make SKILL.md and the script usage examples consistent. Document whether users should run the script with python3, uv run, or a managed virtual environment, and provide a reproducible installation procedure.

  6. Run the Skill in a restricted environment with minimal filesystem access, no unnecessary credentials, and limited network access so that a compromised dependency cannot access unrelated resources.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill declares access to an environment variable (AISA_API_KEY) and requires Python execution, but does not define an explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where a runtime or agent may invoke code paths with broader capabilities than users or reviewers can easily see, increasing the risk of unintended secret use or external calls.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The trigger language is broad enough to match many generic investment questions, which can cause the skill to activate in contexts where a more appropriate or safer skill should be used. Over-broad activation is a security and safety concern because it expands when secrets, tools, or external API access may be used without clear necessity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill title, description, and all user-facing instructions are presented only in Chinese, suggesting a fixed language experience. There is no indication that users may choose another language or that the Chinese-only scope is an intentional, justified locale constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest sets the skill language to "zh", which indicates a fixed locale choice. In this file there is no accompanying user choice, opt-in, or documented region-specific justification, so it appears to enforce a language policy constraint through configuration.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/analyze_stock.py (reported line 115)May include surrounding context.

python
print("❌ Error: AISA_API_KEY environment variable is not set.", file=sys.stderr)
        print("   Set it with: export AISA_API_KEY=your_key_here", file=sys.stderr)
        sys.exit(1)
    base_url = os.environ.get("AISA_BASE_URL", "https://api.aisa.one/v1")
    return OpenAI(api_key=api_key, base_url=base_url)

Vague Triggers

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The usage guidance provides only limited boundaries and does not clearly define when the skill should not trigger beyond a couple of examples. This can lead to unnecessary invocation and increased exposure of API-backed functionality in loosely related conversations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest describes a stock/crypto analysis skill that outputs scores, signals, confidence, and risk prompts. While networked analysis is expected, directly accessing environment variables for credentials and base URL configuration is an additional capability not mentioned in the stated purpose and can expose dependency on external secret material.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.