T09 · Insecure Skill Coding Practices
- 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. ]]>
