Back to skill

Security audit

portfolio-diagnosis (Public)

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed remote Prana wrapper for portfolio analysis, but it can send financial prompts and reusable API credentials to a caller-controlled API endpoint.

Review before installing. This skill forwards portfolio-related prompts to Prana and requires API credentials. Only use it with a trusted Prana endpoint, avoid setting NEXT_PUBLIC_URL or --base-url from untrusted instructions, do not put real brokerage/account secrets in prompts, and rotate the Prana key if it may have been sent to the wrong server.

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

Error
Location
scripts/prana_skill_client.py:27
Finding

Arbitrary API endpoint can receive reusable credentials and sensitive portfolio data

Content
View full analysis

Vulnerability Details

File Location: scripts/prana_skill_client.py, lines 27, 128–133, 259–269, and 299
Vulnerability Type: Unrestricted destination for authenticated network requests
Risk Level: High

Vulnerable Code

python
DEFAULT_PRANA_BASE = os.environ.get(
    "NEXT_PUBLIC_URL",
    "https://suna-dev.ebonex.io",
)
python
def _headers_x_api_key(public_key: str, secret_key: str) -> dict[str, str]:
    """Claw interface requirement: x-api-key is public_key:secret_key."""
    return {
        "Content-Type": "application/json",
        "x-api-key": f"{public_key}:{secret_key}",
    }
python
url = base_url.rstrip("/") + "/api/claw/agent-run"
body = {
    "skill_key": skill_key,
    "question": content,
    "thread_id": thread_id or "",
    "request_id": request_id,
}
data = json.dumps(body, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(
    url,
    data=data,
    method="POST",
    headers=_headers_x_api_key(public_key, secret_key),
)
python
parser.add_argument(
    "--base-url",
    "-b",
    default=DEFAULT_PRANA_BASE,
    help="Prana API root address",
)

Technical Analysis

The client allows its remote API base URL to be selected through either the NEXT_PUBLIC_URL environment variable or the --base-url command-line argument. It then sends the reusable public_key:secret_key credential in the x-api-key header and transmits the user's message in the request body.

No validation restricts the destination to an approved Prana hostname, requires HTTPS, rejects embedded URL credentials, or prevents unusual ports and redirect-based origin changes. Consequently, destination selection crosses a security boundary: an untrusted launcher, wrapper, inherited environment, or copied command can cause locally loaded credentials and portfolio information to be sent to an attacker-controlled server.

The result-recovery calls at lines 278, 283, and 290 are not independently malicious. Reusing ...[truncated 2506 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS

    • Parse the URL with urllib.parse.urlsplit.
    • Reject all schemes except https.
    • Reject missing hostnames, URL user information, fragments, and unsupported ports.
  2. Allowlist trusted API origins

    • Maintain an explicit list of approved Prana hostnames.
    • Compare normalized hostnames exactly; do not use suffix checks vulnerable to names such as trusted.example.attacker.test.
    • Prefer removing --base-url from production releases if arbitrary endpoints are unnecessary.
  3. Protect custom endpoint overrides

    • If development endpoints are required, gate them behind an explicit development mode.
    • Require interactive confirmation before sending credentials to a nonstandard origin.
    • Display the normalized destination without revealing credentials.
  4. Control redirects

    • Disable redirects for authenticated requests or validate every redirect target before forwarding the x-api-key header.
    • Never forward authentication headers across origins.
  5. Reduce credential exposure

    • Use short-lived, narrowly scoped tokens instead of long-lived public_key:secret_key credentials where supported.
    • Scope keys to only the required skill and API routes.
    • Add key rotation and revocation guidance for suspected exposure.
  6. Harden credential storage

    • Prefer environment injection or an operating-system secret store.
    • If files must be supported, require restrictive permissions such as owner read/write only.
    • Ensure credential files are excluded from version control.
  7. Add security tests

    • Verify rejection of http://, attacker-controlled hosts, embedded user information, malformed URLs, unexpected ports, and cross-origin redirects.
    • Verify that authentication headers are sent only to explicitly approved HTTPS origins.
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared behavior is portfolio diagnosis using Tushare and quantitative analytics, but the analyzed skill content appears not to implement that functionality and instead introduces remote service invocation plus API credential handling. That mismatch is dangerous because it can mislead users into providing sensitive financial holdings while the skill performs undisclosed data transmission or secret access outside the stated purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file is a thin remote-execution wrapper that forwards user input to an external Prana service, while the published skill claims to perform local Tushare-based portfolio diagnosis. This mismatch is dangerous because users and reviewers may trust the declared functionality, but the actual behavior delegates execution to an opaque remote backend with different code, data handling, and trust assumptions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file contains user-facing instructions exclusively in Chinese, and there is no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking or region-specific audience. That can violate a language/locale policy requiring user opt-in or clear justification for a forced language choice.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises externally driven functionality and the static analysis detected capabilities consistent with environment access, file reads, and network use, but the manifest does not declare any tool scope or permissions boundaries. In a public skill, missing explicit scoping increases the risk of over-privileged execution, hidden data access, or secret exposure because users and reviewers cannot verify what resources the skill is allowed to touch.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language description, input examples, and trigger phrases are entirely Chinese, with no indication that users may choose another language or locale. Under the policy, a skill should not enforce a specific language unless it offers opt-in or clearly documents a justified regional constraint.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad, conversational, and likely to overlap with normal user discussion about stocks or risk, which can cause unintended activation of the skill. In a finance-related skill, accidental invocation is more concerning because users may disclose portfolio positions, cost basis, and risk preferences without clearly intending to invoke a third-party workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The prominent natural-language description and user-facing strings are written only in Chinese, with no indication that the user can choose another language or locale. Under the language/locale policy, a skill should not impose a specific language without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code loads reusable public/secret API credentials from environment variables or local config files and uses them to authenticate to an external service, even though that capability is not implied by the advertised portfolio-diagnosis purpose. This expands the attack surface: a repackaged or misleading skill can induce operators to provision secrets for a remote platform, enabling data exfiltration, unauthorized remote actions, or credential misuse if the endpoint or package is compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code packages the user's message together with skill-derived parameters and sends them to a remote API without any user-facing disclosure, confirmation, or data-minimization controls. In a financial-analysis context, user prompts may contain holdings, cost basis, account context, or risk preferences, so undisclosed remote transmission creates meaningful privacy and compliance risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes broad, natural investing phrases such as '仓位合理吗' and '帮我分析一下我买的股票', which can easily appear in ordinary conversation and cause unintended activation. Because this skill has both network and filesystem permissions and performs portfolio analysis, accidental invocation could expose sensitive holdings data or trigger unnecessary external/API actions without clear user intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

All user-facing natural-language content in the manifest is limited to Chinese, including the description and activation phrases. This may impose a language constraint without documenting that the skill is Chinese-only, region-specific, or offering an alternative language option.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.