Back to skill

Security audit

unisound-med-rx-safety-ethics

Security checks for vulnerabilities and agentic risk

Overview

The skill’s medical Q&A purpose is coherent, but it needs Review because it can send medical questions and an API key to any caller-supplied endpoint, including unsafe destinations.

Install only if you control the invocation and endpoint configuration. Do not submit identifiable patient data unless the chosen model provider is approved for that data, avoid overriding --api-url except to a trusted HTTPS endpoint, and prefer a safer secret channel than putting API keys directly in shell commands.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run.py:110
Finding
Unrestricted API Endpoint Can Expose Credentials and Sensitive Medical Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run.py:110-119`, `scripts/run.py:218`, and `scripts/run.py:269-277` **Vulnerability Type**: Unrestricted outbound endpoint and credential disclosure **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 argument: ```python p.add_argument("--api-url", default=DEFAULT_API_URL, help="OpenAI 兼容接口地址") ``` The application then passes that value directly to `call_llm`: ```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 resolved network address. The selected endpoint receives an `Authorization: Bearer` header containing the model API key, as well as the complete system prompt and user question. An attacker who can influence command-line parameters or an integration's configuration can redirect the request to an attacker-controlled HTTP server. Because HTTPS is not enforced, the caller can also select a plaintext HTTP endpoint, exposing credentials and medical content to network interception. The unrestricted URL can additionally cause server-side requests to loopback or private-network addresses. Although successful processing expects a JSON response containing `choices`, the outbound request itself occurs before response validation. This means the endpoint still receives the request and its sensitive payload. ### Attack Path 1. An attacker gains ...[truncated 1270 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict endpoints to an explicit allowlist of approved hostnames. 2. Require the `https` scheme and reject plaintext HTTP URLs. 3. Resolve the hostname and reject loopback, link-local, private, multicast, and otherwise prohibited network addresses unless explicitly required. 4. Disable redirects, or validate the scheme, hostname, and resolved address after every redirect before forwarding credentials. 5. Do not attach the authorization header until the destination has passed all validation. 6. Separate credentials by destination so a credential issued for the default provider is never forwarded to another host. 7. If custom endpoints are a necessary feature, require an explicit administrative opt-in and display a warning that prompts and credentials will be transmitted to that destination. 8. Add automated tests covering non-HTTPS URLs, unapproved hosts, private addresses, encoded IP representations, DNS rebinding scenarios, and redirects to prohibited destinations. 9. Require callers to de-identify medical data before submission and document the approved data-handling boundary. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.py:215
Finding
API Credential Accepted Through a Command-Line Argument<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run.py:215` **Vulnerability Type**: Secret exposure through process arguments and command history **Risk Level**: Medium ### Vulnerable Code ```python p.add_argument("--appkey", default="", help="内部医疗大模型鉴权 key。") ``` The documented invocation also encourages supplying the secret directly on the command line: ```bash python3 scripts/run.py --task ethics --question "题干……" --appkey YOUR_KEY ``` ### Technical Analysis Command-line arguments are not an appropriate secret transport mechanism. Depending on the operating system and deployment environment, process arguments can be visible through process-inspection tools, process metadata, monitoring agents, audit systems, job definitions, shell history, debugging output, and orchestration logs. The implementation requires `--appkey` for non-dry-run requests and provides no protected alternative such as an environment variable, secret file descriptor, or secret-manager integration. Although the script does not deliberately print the key, accepting it as an argument increases exposure outside the application's direct control. ### Attack Path 1. An operator follows the documented usage and invokes the script with `--appkey` followed by a valid credential. 2. The shell may save the complete command in its history, or the runtime may expose it through process metadata. 3. A local user, monitoring service, CI log collector, support bundle, or orchestration administrator reads the recorded command. 4. The observer extracts the credential. 5. The credential is reused to submit unauthorized requests to the model API until it expires or is revoked. ### Impact Assessment The attacker obtains the same model-service authorization represented by the exposed key. The resulting scope is limited to the permissions, quota, account, and lifetime associated with that credential. Potential consequences include unauthorized model use, quota or billing consumption, impe ...[truncated 293 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `--appkey` with a protected environment variable or secret-manager lookup. 2. Prefer passing secrets through an inherited file descriptor or a permission-restricted secret file when environment variables are considered too broadly visible. 3. If interactive use is required, read the key with a non-echoing prompt such as `getpass.getpass`. 4. Deprecate and eventually remove command-line secret support. 5. Update all examples and documentation so they no longer place credentials in shell commands. 6. Ensure CI systems and orchestration platforms inject the credential through their native secret mechanisms. 7. Redact authorization values and secret-related configuration from logs, traces, error reports, and support bundles. 8. Rotate any key that has already been supplied through exposed shell history or logged command lines. ]]>
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
93% confidence
Finding
The skill documentation exposes code-backed capabilities that can read files, write files, and make network requests, but it does not declare any explicit tool scope or permissions boundary. In a medical QA/prescription-review context, this is risky because the skill may process sensitive healthcare content, and undeclared I/O or outbound network access increases the chance of unintended data access or exfiltration.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The markdown states the skill should output answers strictly in the format required by the prompt, and the entire skill description and examples are presented as Chinese-only usage for a general-purpose Q&A skill. There is no indication that users may choose another language or that the Chinese-only constraint is justified as a region-specific requirement.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The file-level description and all user-facing CLI/help text are written only in Chinese, and the system prompt is also fixed in Chinese. This imposes a specific language/locale expectation without presenting an explicit language choice or documenting a justified region-specific constraint.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code transmits raw user-supplied medical questions to an external HTTPS API, and those questions may contain sensitive health or personal information. In a medical context, undisclosed off-host transmission materially increases privacy, compliance, and data-governance risk, especially because the tool accepts arbitrary stdin/files and forwards content verbatim.

Static analysis

No suspicious patterns detected.