Back to skill

Security audit

unisound-med-term

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed command-line medical term helper that sends user-provided questions to a configured model API, with no hidden persistence or unrelated behavior found.

Install only if you trust the configured medical model endpoint and can protect the app key. Avoid passing real patient data unless it has been de-identified and approved by your organization, and do not use custom --api-url values from untrusted instructions.

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:75
Finding
Caller-Controlled API Endpoint Exposes Credentials and Medical Input## Vulnerability Details **File Location**: `scripts/run.py:75-83, 205, 258-266` **Vulnerability Type**: Unrestricted transmission of credentials and sensitive input to a caller-controlled endpoint **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("--api-url", default=DEFAULT_API_URL, help="OpenAI compatible endpoint URL") ``` ```python out["answer"] = call_llm( api_url=args.api_url, model=args.model, appkey=args.appkey, system_prompt=args.system_prompt, user_prompt=user_prompt, temperature=float(args.temperature), timeout=int(args.timeout), ) ``` ### Technical Analysis The `--api-url` argument is entirely caller-controlled and is passed directly to `urllib.request.Request`. The program does not require HTTPS, validate the destination hostname against an allowlist, or prevent redirects to an untrusted destination. Every request sends the supplied application key in the `Authorization: Bearer` header. Its JSON body also includes the system prompt and user-provided question. Because the Skill processes medical questions and may receive real patient information, this body can contain sensitive medical or personal data. Consequently, anyone who can influence the command-line arguments can direct the credential and question to an attacker-operated endpoint. A plain HTTP URL can additionally expose this information to network interception. The standard-library HTTP client may follow redirects, further weakening the assumption that the credential is sent only to the intended API. ### Attack Path 1. The attacker creates an HTTP service that records request headers and bodies. 2. The attacker supplies or recommends a command using an endpoint such as: ```bash ...[truncated 1391 chars]
Remediation
## Remediation Suggestions 1. **Restrict the destination** - Use a strict allowlist of approved HTTPS hostnames. - Prefer removing `--api-url` in production if endpoint customization is unnecessary. - Parse the URL and reject unsupported schemes, embedded credentials, unexpected ports, and unapproved hosts. 2. **Enforce secure transport** - Reject all non-HTTPS URLs. - Retain normal TLS certificate and hostname verification. - Consider certificate pinning where operationally appropriate. 3. **Control redirects** - Disable automatic redirects for authenticated requests or validate every redirect target against the same scheme and hostname allowlist. - Never forward the `Authorization` header across an origin change. 4. **Separate credentials by endpoint** - Do not send the default provider credential to a custom host. - Require a separate, explicitly supplied credential for approved custom endpoints. 5. **Protect medical data** - Warn users before transmitting content to a non-default service. - Add input redaction or de-identification controls for patient-related information. - Record destination approval without logging credentials or complete sensitive prompts. 6. **Validate configuration before processing** - Reject unsafe endpoint configuration before reading sensitive input or constructing the authenticated request. - Add tests covering HTTP URLs, unapproved hosts, redirects, user-info components, and unusual ports.
Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill exposes code-backed capabilities to read files, write files, and make network requests, but the manifest does not declare any explicit tool scope or permission boundaries. This creates an unclear trust boundary for deployers and reviewers, increasing the chance that the skill is granted broader access than expected or used in environments where sensitive local data and outbound connectivity are available.

Description-Behavior Mismatch

Low
Confidence
80% confidence
Finding
The manifest language suggests a self-contained skill that can be independently copied and deployed. In practice, successful non-dry execution requires network access to an external API endpoint and an `--appkey`, so the skill is not operationally self-contained despite being code-file self-contained.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The manifest describes a narrowly scoped interface: the caller provides problem text or structured input containing a `question` field. However, the implementation treats any non-JSON/non-JSONL file as raw text and submits its entire contents as the question, which is broader than the described input contract.

Static analysis

No suspicious patterns detected.