Back to skill

Security audit

unisound-chronic-screening

Security checks for vulnerabilities and agentic risk

Overview

The skill performs the advertised health screening, but it needs review because it can send sensitive health records and an API key to a configurable remote endpoint while making privacy claims the code does not enforce.

Install only if you are authorized to send resident health data to the documented medical LLM service and can control how the CLI is invoked. Do not include direct identifiers unless they are removed before input, avoid untrusted --base values, and treat any --output file as sensitive medical data requiring protected storage and retention controls.

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/run.py:45
Finding

Unrestricted LLM Endpoint Override Exposes API Credentials and Sensitive Health Data

Content
View full analysis

Vulnerability Details

File Location: scripts/run.py, lines 45–49, 207, and 221
Vulnerability Type: Server-Side Request Forgery and sensitive-data disclosure through an unrestricted API endpoint
Risk Level: High

Vulnerable code:

python
def make_llm_caller(appkey: str, base: str = DEFAULT_LLM_BASE, model: str = DEFAULT_LLM_MODEL, timeout: int = 0):
    url = f"{base.rstrip('/')}/chat/completions"
    headers = {"Authorization": f"Bearer {appkey}"}

    def llm(messages: List[Dict[str, str]]) -> str:
        payload = {"model": model, "messages": messages, "temperature": 0}
        resp = _http_post(url, payload, headers, timeout=timeout)
python
parser.add_argument("--base", default=DEFAULT_LLM_BASE, help=f"Internal LLM base URL (default: {DEFAULT_LLM_BASE}).")
python
llm = make_llm_caller(args.appkey, args.base, args.model, args.timeout)

Technical Analysis

The command-line --base value is used directly to construct the request destination without validating its scheme, hostname, port, or network range. The application then sends an Authorization: Bearer header containing the supplied platform credential to that destination. The request body also contains the complete health record submitted for chronic-disease screening.

Consequently, any party able to control or influence the command-line arguments can redirect the request to an attacker-controlled server or an unintended internal service. Both HTTP and HTTPS destinations are accepted, so the credential and medical data may also be sent over an unencrypted connection. This violates destination-bound credential handling and least-disclosure principles.

Attack Path

  1. An attacker gains control over, or influences, the arguments used to invoke the Skill.
  2. The attacker sets --base to a server under their control, such as https://attacker.example/v1, or to an unencrypted HTTP endpoint.
  3. The applicati ...[truncated 1159 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the --base override from production builds if endpoint customization is unnecessary.
  • Otherwise, enforce a strict allowlist of approved API hostnames and ports. Parse the URL with urllib.parse.urlsplit and reject user-info components, fragments, unexpected paths, nonstandard ports, and all schemes except HTTPS.
  • Resolve the destination and reject loopback, link-local, private, multicast, reserved, and metadata-service address ranges unless a specifically approved internal endpoint requires them. Revalidate redirects or disable cross-origin redirects.
  • Attach the bearer credential only after confirming that the final request destination is an approved origin. Never forward credentials across redirects to another host.
  • Use endpoint-specific, short-lived, least-privilege credentials so one leaked key cannot access unrelated services.
  • Redact or minimize health information before transmission and obtain appropriate authorization for external processing.
  • Add automated tests confirming that attacker-controlled domains, plain HTTP URLs, embedded credentials, alternate ports, redirect-based bypasses, and internal IP literals are rejected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises file input/output and external network access via its documented run commands and API dependency, but it does not declare any explicit tool scope or permissions. This creates an authorization and governance gap: a caller or platform cannot easily constrain the skill's access to local files or outbound network destinations, which is especially risky in a healthcare context handling sensitive health data and an appkey.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file consistently presents the skill name, description, instructions, inputs, and outputs only in Chinese. Under the policy rule, forcing a specific language without user opt-in can be a natural-language policy violation, and this file does not state that the skill is China-only or otherwise region-restricted.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is designed to process resident health data, then sends that data to a remote LLM endpoint over the network. Because the skill description does not clearly disclose third-party or remote transmission of sensitive medical information, users and operators may unknowingly expose protected health data outside the local environment, creating privacy, compliance, and data-governance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

At the call site, the full resident health record is embedded into the prompt and transmitted to the remote LLM for processing. In a medical-screening context, this materially increases sensitivity because the payload may include diagnoses, lab values, family history, and lifestyle data, and the script provides no explicit warning, consent gate, or redaction step before network disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script can persist screening results to disk, and those results may contain sensitive medical assessments and inferred disease risk. Writing such data without a clear warning or safeguards can lead to unintended retention, insecure sharing, or exposure through backups, shared directories, or downstream tooling.

Content

No source excerpt is available for this finding.