Back to skill

Security audit

unisound-med-record-qc

Security checks for vulnerabilities and agentic risk

Overview

This medical quality-control skill is coherent, but needs review because it can send medical text and an API key to any configured model endpoint without enforced privacy or destination controls.

Install only in an environment where operators understand that submitted medical records may leave the local machine. Use a trusted HTTPS endpoint, avoid overriding --api-url unless the endpoint and credential scope are approved, de-identify real patient data first, and treat the app key as sensitive.

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:102
Finding
Unrestricted API Endpoint Can Exfiltrate Credentials and Sensitive Medical Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run.py`, lines 102–111, 226, and 279–287 **Vulnerability Type**: Unrestricted credentialed outbound request **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) ``` The destination is supplied through an unrestricted command-line option: ```python p.add_argument("--api-url", default=DEFAULT_API_URL, help="OpenAI compatible endpoint URL") ``` The caller-controlled value is then passed directly to the request function: ```python 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` argument accepts an arbitrary URL without validating its scheme, hostname, port, or trust relationship. `call_llm()` sends an `Authorization: Bearer` header containing the supplied application key and a JSON request body containing the complete medical question to that destination. The implementation does not require HTTPS and does not restrict requests to the documented service domain. Consequently, anyone who can influence the command-line configuration can redirect credentialed requests to an attacker-controlled server. If an HTTP URL is used, credentials and medical content may also be exposed to an on-path network attacker. This is particularly sensitive because the skill is designed to process medical records and reports. The project documentation recommends de-identification, but this operational recommendation does not enforce a technical security boundary. ### Attack Path 1. An attacker gains influence over the skil ...[truncated 1477 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Restrict destinations by default** - Permit only the documented API hostname or an explicit allowlist of approved service domains. - Compare parsed, normalized hostnames rather than using substring or suffix checks that can be bypassed. 2. **Require encrypted transport** - Reject every URL whose parsed scheme is not `https`. - Do not provide an option to silently downgrade to plaintext HTTP in production. 3. **Control redirects** - Reject redirects to a different origin. - Do not forward the `Authorization` header across scheme, hostname, or port changes. - Consider disabling redirects entirely for authenticated API calls. 4. **Separate custom endpoints from production credentials** - If custom endpoints are operationally required, require a conspicuous unsafe opt-in. - Require separate credentials scoped specifically to each approved endpoint. - Never attach the production service key to an untrusted custom host. 5. **Apply least privilege to API keys** - Use narrowly scoped, short-lived credentials where supported. - Enforce usage quotas and monitor for anomalous source addresses or request volumes. - Provide a rapid credential-revocation and rotation process. 6. **Reduce sensitive-data exposure** - Enforce or automate de-identification before transmission. - Clearly identify the external data-processing boundary to operators. - Avoid logging authorization headers or complete medical request bodies. 7. **Validate the URL before creating the request** - Parse the URL with a standard URL parser. - Verify the exact scheme, normalized hostname, permitted port, and expected path. - Resolve and reject loopback, link-local, private, and metadata-service addresses unless explicitly required by a trusted deployment design. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents capabilities that imply file read, file write, and network access, but it does not declare any tool scope or permission boundaries in the manifest. That creates an avoidable least-privilege gap: integrators and reviewers cannot easily tell what the skill is expected to access, increasing the risk of overbroad execution in environments where tools are granted implicitly.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The natural-language content of the skill, including the description, usage, parameters, and compliance notes, is exclusively in Chinese. Under the policy, forcing a specific language without user opt-in or a documented justified locale constraint is a language/locale policy violation.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The system prompt is written as a fixed Chinese-language instruction set and does not indicate that users may choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script sends raw `question` content to an external HTTPS API, and the skill is explicitly designed for medical records and imaging-report quality control, so inputs are likely to contain protected health information or other sensitive clinical data. There is no built-in notice, consent gate, redaction step, or locality control before transmission, which makes unintended privacy, compliance, and data-governance violations materially likely in this context.

Static analysis

No suspicious patterns detected.