Back to skill

Security audit

Stock Dividend AIsa

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent read-only dividend research tool, but review is warranted because its API key can be sent to any HTTPS endpoint configured through AISA_BASE_URL.

Install only if you are comfortable sending requested stock tickers and generated analysis prompts to AIsa. Do not set AISA_BASE_URL unless you fully trust that endpoint, because the script will use the same AISA_API_KEY with the configured HTTPS host. Do not provide brokerage credentials or payment details.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/dividends.py:121
Finding

Configurable HTTPS Endpoint Can Receive the AIsa API Key

Content
View full analysis

Vulnerability Details

File Location: scripts/dividends.py, lines 121–130 and 219–227
Vulnerability Type: Unrestricted credential forwarding to a configurable network endpoint
Risk Level: Medium

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", DEFAULT_AISA_BASE_URL).strip().rstrip("/")
    if not base_url.startswith("https://"):
        print("❌ Error: AISA_BASE_URL must use https:// when provided.", file=sys.stderr)
        sys.exit(1)
    return OpenAI(api_key=api_key, base_url=base_url)

The configured client subsequently makes the authenticated request:

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

Technical Analysis

The Skill accepts an arbitrary AISA_BASE_URL and verifies only that its string begins with https://. This enforces encrypted transport but does not establish that the destination is operated by AIsa or otherwise trusted.

The OpenAI client is initialized with both the environment-provided endpoint and AISA_API_KEY. Authenticated requests are therefore sent to whichever HTTPS host the configuration identifies. An attacker who can influence the runtime environment can substitute an attacker-controlled HTTPS endpoint and collect the authentication credential and submitted ticker-analysis prompts.

Network access is necessary for the Skill's declared API-backed dividend-analysis functionality. Sending the credential to the default https://api.aisa.one/v1 endpoint is consistent with that purpose. Allowing the sa ...[truncated 1722 chars]

Remediation
View remediation

Remediation Suggestions

  1. Allowlist the official API host by default. Parse the endpoint structurally and require the normalized hostname to equal api.aisa.one.

    python
    from urllib.parse import urlparse
    
    raw_base_url = os.environ.get(
        "AISA_BASE_URL",
        DEFAULT_AISA_BASE_URL,
    ).strip().rstrip("/")
    
    parsed = urlparse(raw_base_url)
    if (
        parsed.scheme != "https"
        or parsed.hostname != "api.aisa.one"
        or parsed.username is not None
        or parsed.password is not None
        or parsed.fragment
    ):
        print("Error: AISA_BASE_URL must use the trusted api.aisa.one HTTPS endpoint.",
              file=sys.stderr)
        sys.exit(1)
    
  2. Do not forward the AIsa credential to third-party compatible endpoints. If custom endpoints are a required feature, use a separate variable such as CUSTOM_API_KEY and never reuse AISA_API_KEY outside the official AIsa host.

  3. Require explicit opt-in for custom endpoints. Display the normalized destination hostname and require an affirmative configuration flag before transmitting credentials.

  4. Reject ambiguous URLs. Disallow URL user information, malformed hosts, unexpected ports, fragments, and redirects to untrusted hosts. Ensure redirect handling cannot forward authorization headers across origins.

  5. Apply server-side key restrictions. Where supported, scope keys to the minimum required API operations, enforce short expiration periods, limit usage quotas, and restrict keys to expected clients or origins.

  6. Avoid exposing secrets in diagnostics. Continue not printing the credential, and ensure SDK debug logging and exception handling cannot include authorization headers.

  7. Document the trust boundary clearly. Warn that endpoint configuration controls where credentials and query content are transmitted, rather than stating only that the URL should point to a trusted endpoint.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill requires access to an environment secret (AISA_API_KEY) but does not declare an explicit tool/permission scope such as permissions or allowed-tools. Even though the documented behavior is read-only, the lack of explicit scope weakens least-privilege guarantees and makes it easier for a host agent to expose more capability than intended.

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 · SKILL.md (reported line 65)May include surrounding context.

md
from openai import OpenAI


DEFAULT_AISA_BASE_URL = "https://api.aisa.one/v1"
TICKER_PATTERN = re.compile(r"^[A-Z][A-Z0-9.\-]{0,11}$")

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/dividends.py (reported line 26)May include surrounding context.

python
from openai import OpenAI


DEFAULT_AISA_BASE_URL = "https://api.aisa.one/v1"
TICKER_PATTERN = re.compile(r"^[A-Z][A-Z0-9.\-]{0,11}$")

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This code sends the user's requested ticker list and generated prompt content to a remote API via client.chat.completions.create. Although the script logs that it is fetching data via AIsa API, it does not clearly warn that user inputs are transmitted to an external service, which is the type of disclosure this rule looks for in code files.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.