Back to skill

Security audit

unisound-vaccination-reminder

Security checks for vulnerabilities and agentic risk

Overview

The skill’s vaccination-reminder purpose is coherent, but it can send sensitive health records and an API key to a configurable remote service without enforcing the privacy protections it promises.

Review before installing or running with real resident data. Use only de-identified inputs, keep the default trusted HTTPS API endpoint unless you fully control the replacement service, avoid putting production app keys in shell history, and treat any saved output as sensitive medical information.

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

Warning
Location
scripts/run.py:166
Finding
Sensitive medical data is transmitted without enforced de-identification## Vulnerability Details **File Location**: `scripts/run.py:166-185` **Vulnerability Type**: Unredacted transmission of sensitive health information **Risk Level**: Medium The skill documentation states that identifiable information must be de-identified before transmission, but the implementation does not enforce this requirement. ### Vulnerable Code ```python def run_vaccination_reminder(vaccination_info: str, llm, output_path: str = "") -> int: prompt = f"""请根据以下居民信息,生成预防接种提醒。 【居民信息】 {vaccination_info.strip()} 请严格按照要求输出 JSON + 摘要。""" print("正在生成预防接种提醒...") result = llm([sys_msg(SYSTEM_PROMPT), user_msg(prompt)]) ``` The corresponding outbound request is implemented at `scripts/run.py:23-29`: ```python def _http_post(url: str, payload: Dict[str, Any], headers: Dict[str, str], *, timeout: int = 0) -> Any: data = json.dumps(payload, ensure_ascii=False).encode("utf-8") req = urllib.request.Request( url=url, data=data, method="POST", headers={"Content-Type": "application/json", **headers}, ) ``` ### Technical Analysis The complete contents returned by `load_input()` are interpolated directly into the LLM prompt. No validation, data minimization, or redaction is performed before the prompt is serialized and transmitted to the configured external API. Vaccination records are health information and may also contain names, telephone numbers, identity numbers, addresses, or other direct identifiers. Although `SKILL.md:25-28` describes a strict de-identification policy, the code relies entirely on users to sanitize input correctly. This creates a privacy control gap because the documented policy is not enforced at the data boundary. ### Attack Path 1. A user or upstream system creates an input file containing vaccination history and direct identifiers. 2. The file is supplied through the `--input` argument. 3. `load_input()` returns the content without insp ...[truncated 923 chars]
Remediation
## Remediation Suggestions 1. Add a mandatory de-identification stage before constructing the LLM prompt. 2. Detect and remove or tokenize names, identity numbers, telephone numbers, email addresses, precise addresses, medical record numbers, and other direct identifiers. 3. Reject input when sensitive identifiers are detected but cannot be redacted safely. 4. Send only the minimum fields required for vaccination scheduling, such as age range, vaccine history, and clinically relevant conditions. 5. Display the redacted payload for confirmation when the tool is used interactively. 6. Clearly document the API destination, data retention policy, and responsibility for obtaining consent. 7. Add automated tests proving that representative identifiers never appear in serialized outbound request bodies. 8. Avoid including raw request payloads in application, proxy, or API-provider logs.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run.py:42
Finding
Unrestricted API base URL can expose the bearer credential and resident medical data## Vulnerability Details **File Location**: `scripts/run.py:42-51, 221, 239` **Vulnerability Type**: Credential and sensitive-data exfiltration through an unrestricted endpoint **Risk Level**: High The command-line interface accepts an arbitrary API base URL. The application then sends both the bearer credential and the complete medical prompt to that destination without validating its scheme or hostname. ### 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) try: return resp["choices"][0]["message"]["content"].strip() except (KeyError, IndexError, TypeError) as e: raise RuntimeError(f"Unexpected LLM response: {resp}") from e ``` The unrestricted option is declared at `scripts/run.py:221` and used at `scripts/run.py:239`: ```python parser.add_argument("--base", default=DEFAULT_LLM_BASE, help=f"内部大模型 base URL(默认:{DEFAULT_LLM_BASE})。") ``` ```python llm = make_llm_caller(args.appkey, args.base, args.model, args.timeout) ``` ### Technical Analysis The `--base` value is incorporated directly into the request URL. There is no enforcement of HTTPS, no allowlist of approved API hosts, and no check that the bearer credential is being sent to the intended service. Consequently, a malicious command, wrapper script, copied usage example, or configuration can redirect requests to an attacker-controlled server. The request contains two valuable assets: - The API key in the `Authorization: Bearer` header. - The complete LLM message payload, including resident vaccination and health informati ...[truncated 1425 chars]
Remediation
## Remediation Suggestions 1. Remove the `--base` option in production builds when endpoint customization is not operationally necessary. 2. Allowlist exact approved HTTPS origins, including the expected hostname and port. 3. Reject plain HTTP URLs, embedded credentials, unexpected ports, fragments, and malformed URLs. 4. Resolve and validate the final destination before attaching the authorization header. 5. Prevent credentials from being forwarded to a different origin during redirects, or disable redirects for authenticated requests. 6. Require an explicit development-only unsafe flag before permitting a custom endpoint, and never reuse production credentials in that mode. 7. Store the API key in a protected environment variable or secret manager rather than exposing it in command-line arguments, which may be visible in process listings and shell history. 8. Use separate restricted credentials with minimal API permissions, short expiration periods, and limited quotas. 9. Add tests confirming that unauthorized schemes and hosts are rejected before any network request is made. 10. Rotate the application key immediately if the skill has previously been run against an untrusted endpoint.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill documents file input/output and outbound network access to an internal medical model API, but it does not declare any explicit tool scope or permissions. In an agent platform, missing capability declarations weaken least-privilege controls and make it harder for reviewers or runtime policy to constrain what the skill is allowed to do, which is especially sensitive because the input may contain health-related personal data and the skill writes results to disk and sends data over the network.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The description is written as a Chinese-only user instruction and specifies output as “JSON + 自然语言摘要,” while the rest of the skill documentation consistently assumes Chinese-language use. There is no opt-in, alternative language option, or explicit justification that the skill is restricted to Chinese-language workflows, which matches the locale-policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
Natural-language instructions, prompts, output format, and user-facing messages all require Chinese, and there is no opt-in or alternative language path. This creates a language policy concern because the skill effectively forces a specific locale rather than offering user choice or explicitly documenting a justified region-specific limitation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The code sends resident vaccination history and special health conditions directly to a remote LLM API, which is highly sensitive medical data. Although the endpoint uses HTTPS, the script provides no explicit consent flow, warning, minimization, or redaction, so operators may disclose protected health information to a third-party service without realizing it.

Ssd 3

Medium
Confidence
96% confidence
Finding
Untrusted resident-provided text is interpolated directly into the user prompt, so any instructions embedded in the medical record can influence model behavior, override formatting expectations, or cause sensitive content to be echoed back. In this medical context, prompt injection can lead to unsafe vaccination guidance, malformed JSON, or disclosure/amplification of sensitive notes in output.

Static analysis

No suspicious patterns detected.