Back to skill

Security audit

Medical Unit Converter

Security checks for vulnerabilities and agentic risk

Overview

This is a simple local medical lab unit converter with some documentation and validation issues, but no evidence of hidden access, persistence, exfiltration, or unsafe agent behavior.

This skill is reasonable to install for local lab unit conversion, but treat reference ranges as informational only and not medical advice. Be aware that its documentation does not fully match the script: it supports more analytes than listed, emits different JSON field names than documented, and should reject NaN or infinite values before use in automated workflows.

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

Warning
Location
scripts/main.py:121
Finding
Non-Finite Numeric Values Bypass Input Validation## Vulnerability Details **File Location**: `scripts/main.py`, lines 121–137, 142, and 164 **Vulnerability Type**: Improper numeric input validation and non-standard JSON serialization **Risk Level**: Medium ### Vulnerable Code ```python def convert(value: float, analyte: str, from_unit: str, to_unit: str) -> dict: """Perform the conversion and return a result dict.""" analyte_key = analyte.lower() from_key = normalise_unit(from_unit) to_key = normalise_unit(to_unit) lookup = (analyte_key, from_key, to_key) if lookup not in CONVERSIONS: supported = ", ".join(SUPPORTED_ANALYTES) print( f"Error: unsupported conversion '{from_unit}' → '{to_unit}' for analyte '{analyte}'.\n" f"Supported analytes: {supported}", file=sys.stderr, ) sys.exit(1) conv = CONVERSIONS[lookup] output_value = round(value * conv["factor"], 4) return { "analyte": analyte, "input_value": value, "input_unit": from_unit, "output_value": output_value, "output_unit": to_unit, "reference_range": conv["reference_range"], } ``` ```python parser.add_argument("--value", type=float, required=True, help="Numeric value to convert") ``` ```python print(json.dumps(result, indent=2)) ``` ### Technical Analysis The `--value` argument uses Python's `float` converter, which accepts special IEEE-754 values such as `nan`, `inf`, and `-inf`. The conversion function does not verify that the parsed value is finite before performing the calculation. Python's default `json.dumps()` behavior permits these values and serializes them as `NaN`, `Infinity`, and `-Infinity`. These tokens are not valid numbers under the strict JSON specification. Consequently, the program can produce medically meaningless results that may either be accepted by permissive consumers or rejected by strict JSON parsers. ### Attack Path 1. Invoke the converter with a supported analyt ...[truncated 1127 chars]
Remediation
## Remediation Suggestions 1. Reject all non-finite values immediately after argument parsing and within `convert()` so direct programmatic callers receive the same protection: ```python import math if not math.isfinite(value): raise ValueError("--value must be a finite numeric value") ``` 2. Convert validation failures into the documented user-facing error: ```python if not math.isfinite(args.value): parser.error("--value must be a finite numeric value") ``` 3. Disable non-standard JSON number serialization as defense in depth: ```python print(json.dumps(result, indent=2, allow_nan=False)) ``` 4. Add tests covering `nan`, `inf`, `-inf`, extremely large finite values, negative values, and ordinary valid values. 5. Consider rejecting negative laboratory measurements or applying documented analyte-specific plausibility limits where medically appropriate. Such limits should be sourced and explicitly documented rather than inferred.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Self-Modification

High
Category
Rogue Agent
Content
"observed_in": [],
      "problem": "SKILL.md Output Format shows 'converted_value' and 'formula' fields, but the script outputs 'output_value', 'input_value', and 'input_unit' without a 'formula' field. Agents parsing the output by field name will fail.",
      "root_cause": "Script was implemented with different field names than the SKILL.md spec without updating the documentation.",
      "fix": "Either add a 'formula' field to the convert() output (e.g., f'{value} x {factor}') and rename output_value to converted_value, or update SKILL.md Output Format to match the actual script output."
    },
    {
      "priority": "P2",
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
The required out-of-scope response is written as a fixed English message, which can impose a specific language on users regardless of their locale or preferred language. The file does not indicate that the response language should follow user preference or offer any language choice.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The documented output schema does not match the actual emitted fields, which can cause downstream agents or automation to misparse results or silently fail open. In a medical-data-processing context, schema confusion can lead to incorrect handling of laboratory values, omitted formula transparency, or misuse of converted values in later steps, making this more serious than a normal docs bug.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This skill produces medical conversions alongside clinical reference ranges, which can cause users to treat the output as clinical guidance rather than simple unit conversion. In a healthcare context, missing a clear disclaimer and safety warning increases the risk of inappropriate self-diagnosis or treatment decisions based on decontextualized results.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest description explicitly scopes supported analytes to four items, but the conversion table implements several additional analytes. This is a semantic mismatch between the declared capability and the actual behavior of the skill.

Description-Behavior Mismatch

Low
Confidence
98% confidence
Finding
The manifest says the skill supports glucose, cholesterol, creatinine, and hemoglobin conversions, but the audited code behavior is documented here as covering additional analytes: triglycerides, urea, calcium, sodium, and potassium. This is a description-behavior mismatch because the implemented scope is broader than the stated manifest purpose.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The audit records that SKILL.md documents only 4 analytes while the script actually supports 9. This is an intent-code divergence because the documentation actively presents a narrower set of supported conversions than the code implements.

Static analysis

No suspicious patterns detected.