T09 · Insecure Skill Coding Practices
- Location
scripts/run.py:75- Finding
Prompt Injection Through Untrusted Assessment Content
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is not overtly malicious, but it needs review because it sends patient assessment data to a fixed external medical-model API and can load preprocessing code from outside the package.
Review this before installing in any real patient or clinical workflow. Use it only if the fixed hivoice.cn model endpoint is approved for the health data being processed, users explicitly consent to sending assessment contents externally, and the external processor's retention and compliance terms are acceptable. Prefer JSON input with minimal identifiers, avoid uploading sensitive documents unless necessary, and ensure any _shared preprocessing directory is trusted and not writable by unprivileged users.
scripts/run.py:75Prompt Injection Through Untrusted Assessment Content
scripts/run.py:21Mandatory External Disclosure of Patient Assessment Data
scripts/run.py:194Dynamic Execution of an Unverified External Preprocessing Module
The skill presents itself as questionnaire construction/assessment, but it also sends assessment content to an external network endpoint and requires an API key, which is a materially different behavior from local form handling. In a medical context, this is especially dangerous because patient responses may contain sensitive health information that is transmitted off-system without clear up-front disclosure and consent.
The skill presents itself as questionnaire construction/assessment, but it also sends assessment content to an external network endpoint and requires an API key, which is a materially different behavior from local form handling. In a medical context, this is especially dangerous because patient responses may contain sensitive health information that is transmitted off-system without clear up-front disclosure and consent.
The file implements a broad local document ingestion and transformation utility that is materially unrelated to a patient self-assessment questionnaire skill. This mismatch increases the likelihood of hidden data collection, unnecessary attack surface, and processing of sensitive local files beyond user expectations, especially in a medical context where users may provide highly sensitive records.
The skill adds local document conversion and OCR capabilities that are not directly required for postoperative self-assessment, enabling ingestion of arbitrary user files through complex external parsers. In a healthcare-related skill, this broad capability is dangerous because it can process sensitive medical documents and substantially increases exposure to parser exploits, over-collection of data, and unexpected local file handling.
The skill advertises capabilities that imply file access, shell execution, environment access, and network use, but it does not declare any explicit tool scope or permissions boundary. This is dangerous because operators and users cannot accurately assess what the skill may access, and the combination of document parsing plus shell/network access increases the chance of unintended data exposure or command abuse.
The documentation states that assessment content is sent to an internal medical model API, but it does not provide an explicit warning about privacy, data sharing, or handling of potentially sensitive medical information. Because the skill is for postoperative patient self-assessment, the data is likely health-related, so silent transmission creates a meaningful confidentiality and compliance risk.
User files are sent through external conversion and OCR tools without any evident user-facing warning, consent flow, or disclosure in the code. For a medical self-assessment skill, silent processing of potentially sensitive documents is risky because users may not realize their files are being transformed by third-party binaries with distinct privacy and security implications.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if not office_bin:
raise PreprocessError("libreoffice/soffice not found for office document conversion.")
with tempfile.TemporaryDirectory(prefix="med-skill-preprocess-") as tmp_dir:
proc = subprocess.run(
[office_bin, "--headless", "--convert-to", "txt:Text", "--outdir", tmp_dir, str(path)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False,
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if not office_bin:
raise PreprocessError("libreoffice/soffice not found for xls conversion.")
with tempfile.TemporaryDirectory(prefix="med-skill-preprocess-") as tmp_dir:
proc = subprocess.run(
[office_bin, "--headless",
"--convert-to", "csv:Text - txt - csv (StarCalc):44,34,76,1",
"--outdir", tmp_dir, str(path)],
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
pass
pdf_to_text = shutil_which("pdftotext")
if pdf_to_text:
proc = subprocess.run(
[pdf_to_text, "-layout", str(path), "-"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False,
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd = [tesseract_bin, str(path), "stdout"]
if lang_arg:
cmd.extend(["-l", lang_arg])
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False)
if proc.returncode != 0 or not proc.stdout.strip():
raise PreprocessError(f"Image OCR failed: {proc.stderr.strip() or 'no text returned'}")
return proc.stdout
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def detect_tesseract_langs(tesseract_bin: str) -> Sequence[str]:
proc = subprocess.run(
[tesseract_bin, "--list-langs"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False,
)
The skill’s stated purpose is narrow self-assessment interpretation, but the code hard-depends on a remote chat-completions API and model capability. This expands the data exposure surface and operational privileges beyond what is obviously required for simple questionnaire scoring, increasing the chance of unnecessary external processing of sensitive medical information.
The skill sends detailed patient self-assessment contents, scores, questions, answers, assessment ID, and timestamp to an external remote LLM service. In a medical context, this is sensitive health data processing and creates privacy, compliance, and third-party exposure risk, especially because the transfer is not minimized, consent-gated, or clearly disclosed in the code path.
The code transmits assessment metadata and answer contents to a remote API without any visible user-facing disclosure, consent flow, or privacy notice in the execution path. For a patient-facing rehabilitation self-assessment skill, this omission is dangerous because users may reasonably expect local processing and may unknowingly disclose protected health information to a third party.
The skill mandates a specific remote model/API path and states that execution must use API inference, without presenting a user choice or opt-in. While not inherently exploit code, this forced remote execution weakens user control over where sensitive questionnaire data is processed and increases privacy risk in a healthcare setting.
The module docstring is written entirely in Chinese and later OCR logic prefers the Chinese Simplified plus English Tesseract language set when available. This indicates a language/locale preference without any visible opt-in or documented language choice for users.
The system prompt is written to require the model to respond in Chinese and does not provide any user opt-in or language-selection mechanism. This is a natural-language locale policy issue because the skill imposes a specific language by default rather than letting the user choose.