Back to skill

Security audit

unisound-med-medication-rehab

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but it can send sensitive medical questions and an API key to any caller-supplied endpoint, so it needs careful review before use.

Review this before installing in any real medical or patient-data workflow. Use only a trusted HTTPS API endpoint, do not override --api-url unless you control the destination, de-identify patient details before submission, protect the API key, and treat any --output files as sensitive records.

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:105
Finding
Unrestricted API Endpoint Can Expose Bearer Credentials and Sensitive Medical Data## Vulnerability Details **File Location**: `scripts/run.py:105-112`, `scripts/run.py:225`, `scripts/run.py:238-244`, and `scripts/run.py:282-290` **Vulnerability Type**: Unrestricted outbound endpoint and insecure command-line credential handling **Risk Level**: High ### Vulnerable Code ```python req = Request( api_url, data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), headers={ "Content-Type": "application/json", "Authorization": f"Bearer {appkey}", }, ) resp = urlopen(req, timeout=timeout) ``` ```python p.add_argument("--appkey", default="", help="Internal medical model authentication key.") p.add_argument("--api-url", default=DEFAULT_API_URL, help="OpenAI-compatible endpoint URL") ``` ```python if not args.appkey: print("error: non-dry-run execution requires --appkey", file=sys.stderr) return 2 out["answer"] = call_llm( api_url=args.api_url, model=args.model, appkey=args.appkey, system_prompt=system_prompt_for(task_key, args.system_prompt), user_prompt=user_prompt, temperature=float(args.temperature), timeout=int(args.timeout), ) ``` ### Technical Analysis The `--api-url` option accepts an unrestricted user-supplied URL. The value is passed directly to `urllib.request.Request`, and the request includes both the bearer credential in the `Authorization` header and the complete user question in the JSON body. The implementation does not require HTTPS, validate the destination hostname, or restrict the endpoint to a trusted allowlist. Consequently, an HTTP endpoint can receive the credential and medical content in plaintext, while an attacker-controlled HTTPS endpoint can directly collect both values. The API credential is also supplied through `--appkey`. Command-line arguments can be exposed through process inspection facilities and may be retained in shell history when entered interactively. This inc ...[truncated 1723 chars]
Remediation
## Remediation Suggestions 1. Remove unrestricted endpoint selection in production, or enforce an explicit allowlist of approved HTTPS schemes, hostnames, and ports. 2. Reject non-HTTPS URLs before constructing the request. Normalize and parse URLs with `urllib.parse.urlsplit` rather than validating them through string-prefix checks. 3. Prevent redirects to unapproved destinations, or validate every redirect target before forwarding any request containing credentials. 4. Load the API key from a protected environment variable, operating-system credential store, or secrets manager instead of accepting it as a command-line argument. 5. If interactive credential entry is necessary, use a non-echoing input mechanism such as `getpass`. 6. Use a dedicated, least-privileged API credential with limited scope, quota, and lifetime. Rotate the current credential if it may have been exposed. 7. Clearly warn operators that medical input is transmitted to the configured external service and require de-identification before submission. 8. Add automated tests confirming that plaintext HTTP, unapproved hosts, and redirects to unapproved hosts are rejected before the authorization header or request body is transmitted.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The caller can fully override the API endpoint via --api-url, allowing the tool to send prompts, metadata, and possibly sensitive medical content to any attacker-controlled server. In environments where this skill is trusted as a narrowly scoped medical helper, that becomes an arbitrary outbound exfiltration channel.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill documentation advertises capabilities that imply file reading, file writing, and outbound network access, but it does not declare any explicit tool scope or permission boundaries. This creates an avoidable trust gap: integrators and reviewers cannot easily determine what resources the skill is intended to access, increasing the chance of over-privileged deployment and unintended data exposure, especially because the skill processes potentially sensitive medical questions and sends them to a remote API.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The natural-language content of the skill description and usage instructions is entirely in Chinese, which effectively forces a specific language for users reading or integrating the skill. The policy allows language constraints only when users are offered a choice or when the constraint is clearly documented and justified; neither is present here.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The base system prompt is entirely in Chinese and instructs the model in that language, which effectively fixes the interaction locale. There is no opt-in, language selection mechanism, or documented justification that this skill is intentionally limited to Chinese-only use.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
Medical questions may contain protected health information, and the script transmits the full prompt to a remote API without any prominent disclosure, confirmation step, or sanitization. In a medical-use context, silent transmission of potentially sensitive health data materially increases privacy and compliance risk.

Description-Behavior Mismatch

Medium
Confidence
83% confidence
Finding
The skill is presented as a medical Q&A tool, but it also accepts arbitrary file input, reads entire file contents, and can forward that content to a remote LLM API. This creates a data-handling mismatch: operators may provide local files assuming local processing, while sensitive content is actually exfiltrated to an external service.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script persists full question text, metadata, and answers to disk, which can include sensitive medical details and identifiers from the input record. Writing this data without warning, minimization, or access-control guidance increases the chance of local exposure through logs, backups, shared workspaces, or misconfigured permissions.

Static analysis

No suspicious patterns detected.