Back to skill

Security audit

NutriGx Advisor

Security checks for vulnerabilities and agentic risk

Overview

The skill is a local genetic-nutrition reporter, but it needs review because it stores exact genotype data despite saying it will not and generates an unsafe reproducibility shell script.

Review before installing. Only use it with your own DNA data or data you have clear consent to analyze, keep the output directory private, and assume the report and images contain sensitive genetic information. Do not run the generated commands.sh for analyses involving untrusted or unusual file paths until the shell quoting issue is fixed. Treat the nutrition and supplement recommendations as educational and discuss significant changes with a qualified clinician.

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

Error
Location
repro_bundle.py:44
Finding
Shell Command Injection in Generated Reproducibility Script<![CDATA[ ## Vulnerability Details **File Location**: `repro_bundle.py:44-60` **Vulnerability Type**: Shell command injection through unquoted user-controlled arguments **Risk Level**: High ### Vulnerable Code ```python # commands.sh cmd_args = " ".join(f"--{k.replace('_', '-')} {v}" for k, v in args.items() if v and k != "synthetic") commands = f"""#!/usr/bin/env bash # NutriGx Advisor — Reproducibility Script # Generated: {timestamp} # ClawBio NutriGx Advisor v0.1.0 set -euo pipefail # 1. Create conda environment conda env create -f environment.yml conda activate nutrigx-advisor # 2. Run analysis python nutrigx_advisor.py {cmd_args} # 3. Verify checksums sha256sum -c checksums.txt """ ``` ### Technical Analysis The application passes command-line arguments into `create_reproducibility_bundle()` through `vars(args)`. The values include user-controlled input, output, and custom-panel paths. At line 44, these values are converted directly to shell command text without quoting or escaping. The generated text is then embedded in `commands.sh`, which is explicitly intended to be executed to reproduce the analysis. Shell metacharacters inside a path—such as semicolons, command substitutions, redirections, or newline characters—will consequently be interpreted by Bash when the generated script is run. The initial analysis does not immediately execute the injected shell syntax because it is only written to a file. Exploitation occurs when a user subsequently executes `commands.sh`. The generator also serializes boolean options as option-value pairs, such as `--no-figures True`, even though the original CLI defines them as flags. This may prevent reliable reproduction, although the command-injection issue remains the primary security concern. ### Attack Path 1. An attacker supplies a genetic-data file or recommends an output or panel path containing shell syntax. For example, a path could contain a command substitution such as `$(malicious-command)`. 2. T ...[truncated 1083 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Apply `shlex.quote()` separately to every command-line value before inserting it into shell text. - Use an explicit allowlist of supported arguments instead of serializing every dictionary entry. - Serialize boolean flags only when enabled and do not append a `True` or `False` value. - Reject argument values containing newline or NUL characters before generating shell files. - Prefer a structured JSON argument manifest and a Python reproduction launcher that invokes the application with an argument list rather than generating shell command text. - If a shell script must be produced, construct arguments as a safely quoted Bash array. - Add automated tests covering spaces, quotes, semicolons, redirections, `$()`, backticks, newlines, and leading hyphens. A safer quoting approach would be: ```python import shlex cmd_parts = [] for key, value in args.items(): if key == "synthetic" or value in (None, False): continue option = f"--{key.replace('_', '-')}" cmd_parts.append(shlex.quote(option)) if value is not True: cmd_parts.append(shlex.quote(str(value))) cmd_args = " ".join(cmd_parts) ``` The generated script should also resolve its own directory and invoke known files through absolute or script-relative paths. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
generate_report.py:173
Finding
Sensitive Genotype Data Is Written to Reports Contrary to the Privacy Guarantee<![CDATA[ ## Vulnerability Details **File Location**: `generate_report.py:173-184`; contradictory privacy statement at `SKILL.md:215-219` **Vulnerability Type**: Unexpected plaintext disclosure of sensitive genetic information **Risk Level**: Medium ### Vulnerable Code The Skill documentation states: ```markdown ## Privacy All computation runs **locally**. No genetic data is transmitted. Input files are read-only; no raw genotype data appears in any output file (reports contain only gene names, SNP IDs, and risk categories). ``` However, report generation includes exact genotypes: ```python if data["contributing_snps"]: lines += [ "| Gene | rsID | Genotype | Risk Alleles | Effect |", "|------|------|----------|:------------:|--------|", ] for s in data["contributing_snps"]: effect = s["effect_direction"].replace("_", " ").title() lines.append( f"| {s['gene']} | {s['rsid']} | `{s['genotype']}` " f"| {s['risk_count']}/2 | {effect} |" ) lines.append("") ``` The committed example confirms that this behavior occurs in practice: ```markdown | MTHFR | rs1801133 | `CT` | 1/2 | Decreased Folate Conversion | | VDR | rs731236 | `CC` | 2/2 | Decreased Vitamin D Response | | APOE | rs429358 | `TT` | 0/2 | Increased Ldl On Saturated Fat | ``` ### Technical Analysis Genotypes are inherited, identifying, and medically sensitive data. Although the report contains only panel SNPs rather than the complete source genome, the exact allele calls remain genetic data. The implementation copies each normalized genotype into `nutrigx_report.md`. This behavior directly contradicts the documented statement that no raw genotype data appears in output files. A user relying on that statement may treat the report as de-identified and share, upload, synchronize, or archive it without protections appropriate for genetic records. The output is written using ordinary filesystem defaults: ```python report ...[truncated 1851 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove exact genotype values from reports by default. - Report only derived risk categories or aggregate risk-allele counts when those values are sufficient for the stated purpose. - Add an explicit option such as `--include-genotypes` for users who knowingly choose to include exact allele calls. - Display a prominent warning before generating genotype-bearing output and clearly label such reports as sensitive genetic records. - Correct `SKILL.md` so that its privacy statement precisely describes every output field. - Consider creating sensitive output files with owner-only permissions, such as mode `0600`, where the operating system supports it. - Avoid placing genotype-bearing reports in shared or predictable directories by default. - Add tests that verify the default report does not contain genotype strings. - Document retention, deletion, backup, and sharing risks for generated reports. - Review all additional artifacts and charts to ensure they disclose only the minimum information necessary for the analysis. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The introductory description explains functionality but does not prominently warn users that the skill handles extremely sensitive genetic and health-adjacent data, which can lead to uninformed use and unsafe sharing of raw genome files. This omission is more serious here because the skill invites uploads of consumer DNA files and produces personalized health-related outputs, so users need clear upfront notice before engaging.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are broad enough to activate this skill for generic nutrition or genetics requests, which can cause the orchestrator to route users into a workflow that processes highly sensitive genetic data or provides genotype-based recommendations when the user did not clearly request that. In this context, misrouting is more dangerous than usual because the skill deals with health-related interpretation of DNA data, so an overly permissive trigger surface increases privacy and safety risk.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if args.no_figures:
                cmd.append("--no-figures")
            print(f"[generate_patient] Running: {' '.join(cmd)}")
            subprocess.run(cmd, check=True)


if __name__ == "__main__":
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Ae4

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

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The document says it is not medical advice, but then gives individualized, genotype-based recommendations such as target vitamin D levels, supplement preferences, dosage-like intake caps, and nutrient interventions. In a genetics context, this can cause users to act on quasi-clinical guidance without appropriate review, creating health and liability risk despite the disclaimer.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The report provides actionable supplement and dietary guidance based on genetic data without nearby warnings about the sensitivity of genomic information or a strong clinician-review checkpoint at the recommendation site. Because genomic data is highly sensitive and health recommendations may be misunderstood as prescriptive, the context makes this more dangerous than generic nutrition content.

Ae4

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

Skill Enumeration

Medium
Category
Agent Snooping
Content
"## References",
        "",
        "SNP-nutrient associations sourced from GWAS Catalog, ClinVar, and CPIC guidelines.",
        "Full citations available in `skills/nutrigx-advisor/SKILL.md`.",
        "",
    ]
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
"## References",
        "",
        "SNP-nutrient associations sourced from GWAS Catalog, ClinVar, and CPIC guidelines.",
        "Full citations available in `skills/nutrigx-advisor/SKILL.md`.",
        "",
    ]
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This function writes a detailed personalized genetic nutrition report to disk, including sensitive health/genetic risk interpretations and the input filename, without any explicit consent gate, warning, or privacy-preserving controls in this code path. If the output directory is shared, backed up, synced, or readable by other users/processes, this can expose highly sensitive personal data and create compliance/privacy risks.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The code saves radar and heatmap image files that encode genetic risk information to disk without an explicit warning or consent step in this file. These images may be easier to casually view, copy, index, or share than the main report, increasing the chance of unintended disclosure of sensitive genetic/health inferences.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This CLI skill processes highly sensitive genetic data and creates output artifacts, including a reproducibility bundle, without any explicit privacy notice, consent prompt, or description of how input data will be stored and copied. In the context of genomic data, silent handling and duplication of files materially increases the risk of unintended retention, disclosure, or insecure downstream use by operators who may not realize the sensitivity of the data.

Intent-Code Divergence

Low
Confidence
96% confidence
Finding
The module docstring states that using --run produces output in "nutrigx_results_<seed>/", but the implementation writes results to "examples/output/results_<seed>". This is an active contradiction between the documented behavior and the actual file location, not just an omitted detail.

Missing User Warnings

Low
Confidence
89% confidence
Finding
This code writes several files to disk, including commands.sh, environment.yml, checksums.txt, and provenance.json, but the function contains no confirmation prompt, print/log message, or inline warning to inform the user at execution time. For code files, file writes are safety-relevant operations when there is no visible disclosure in code or comments explaining the action to the user.

Static analysis

No suspicious patterns detected.