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

Content
View full analysis

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
View 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
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.

Content

Scanner excerpt · medical-unit-converter_audit_result_v4.json (reported line 269)May include surrounding context.

json
"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",

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.