T09 · Insecure Skill Coding Practices
- Location
scripts/run.py:120- Finding
Indirect Prompt Injection Through Untrusted Medication Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This medication reminder skill has review-worthy privacy and execution risks because it sends medication details to a remote model and includes broad document/OCR processing plus an unverified shared-code fallback.
Review carefully before installing. Use it only if you accept sending medication details and an API bearer key to the documented remote model service. Avoid real patient data unless the provider, retention terms, and compliance posture are acceptable. Prefer JSON input over document/OCR input, and do not rely on the generated Markdown as medical advice or dose guidance.
scripts/run.py:120Indirect Prompt Injection Through Untrusted Medication Data
scripts/run.py:220Bearer API Key Exposed Through Command-Line Arguments
scripts/run.py:240Unverified Dynamic Execution of Python Code Outside the Skill Package
The skill is presented as reminder generation, yet it requires remote API access and bearer-token authentication to send medication-related content to an external medical model service. This undisclosed external dependency changes the trust and data-flow model significantly, creating risk of sensitive data exposure and misuse of provided credentials.
The skill is presented as reminder generation, yet it requires remote API access and bearer-token authentication to send medication-related content to an external medical model service. This undisclosed external dependency changes the trust and data-flow model significantly, creating risk of sensitive data exposure and misuse of provided credentials.
The script is a broad document-ingestion and OCR utility handling pdf/doc/docx/xls/xlsx/csv/json/text/images, which does not match a medication-reminder skill's stated purpose. That mismatch materially raises suspicion because unrelated high-complexity parsing capability can be used to exfiltrate, process, or stage sensitive patient documents beyond the minimum required functionality.
The skill contains subprocess-driven OCR and office/PDF conversion capabilities that are not obviously necessary for reminder workflows, creating an unjustified attack surface. In a healthcare context, this is more dangerous because such ingestion can pull in sensitive patient documents and run external parsers on them, increasing both compromise and privacy risk.
The function packages medication name, dose, reminder times, status, and a three-day schedule into prompts sent to a remote API, but the user-facing CLI and output provide no warning that medical data leaves the local environment. For a patient medication reminder skill, undisclosed exfiltration of health-related data is especially sensitive and can violate user expectations, policy, or regulation.
The skill documents capabilities that imply shell, filesystem, environment, and network access, but it declares no explicit tool scope or permission boundaries. In a medical-reminder context, that creates unnecessary ambient authority: the skill could read local files, invoke external binaries, and transmit medication data off-box without clear restriction or user understanding.
The skill claims it only manages reminders and does not make medical judgments, but its documented output includes medical-model-generated interpretation, analysis, and reminder text. That scope expansion can mislead users into relying on generated medical-style guidance that exceeds the stated safe boundary of simple scheduling.
Mandatory use of a remote medical LLM is not justified for basic reminder scheduling, which can be implemented locally and deterministically. Requiring external inference increases attack surface, introduces unnecessary data exfiltration risk, and creates dependency on credentials and network services for a low-complexity task.
Medication names, doses, schedules, and dates are health-related data, and the documentation states they are sent to a remote medical model API without any prominent privacy warning or consent flow. In the healthcare context, silent transmission of such data is especially sensitive and can violate user expectations, internal policy, or regulatory requirements.
The module docstring is written entirely in Chinese and does not indicate any user choice of language or locale. This can violate language/locale policy when the skill is expected to be generally usable without forcing a specific language.
Although the code avoids shell injection by passing argv as a list, it invokes LibreOffice on attacker-supplied document content. Running complex document converters on untrusted files expands attack surface substantially, and historically such parsers have had memory-corruption and document-triggered exploitation issues.
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,
)
This launches LibreOffice to convert legacy xls input, again exposing the system to a large external parser on untrusted documents. The main risk is not shell injection but unsafe processing of hostile file formats that may trigger vulnerabilities or cause denial of service.
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)],
Invoking pdftotext on untrusted PDFs increases exposure to parser bugs and decompression/resource-exhaustion issues. This is lower risk than shell injection because the command is constructed safely, but it still expands the trusted computing base beyond the medication-reminder skill's needs.
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 code introduces an external API dependency and requires a separate appkey for a simple medication reminder workflow that is otherwise computed locally. This expands the attack surface, creates opportunities for credential misuse or accidental disclosure, and is not clearly justified by the stated purpose of the skill.
The skill sends patient medication details, dosage, schedule, and status to an external LLM API to generate friendly reminder text. In a medical context, this is sensitive health information, and transmitting it off-device/service boundary without explicit consent, disclosure, data handling guarantees, or minimization creates a real privacy and compliance risk.
The system prompt hardcodes Chinese instructions and patient-facing output style, which effectively constrains the skill to a specific language/locale. There is no opt-in, language selection, or documented justification for limiting output to Chinese only.
The skill description and all documented output conventions are presented only in Chinese, including the expected skill name and examples, with no indication that users may choose another language or locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is explicitly justified.
Detected: suspicious.dynamic_code_execution