T09 · Insecure Skill Coding Practices
- Location
scripts/orchestrator.py:42- Finding
Argument Injection Through Unsafe Saved-Output Substitution
- Content
View full analysis
Vulnerability Details
File Location:
scripts/orchestrator.py, lines 42–57 and 128–163
Vulnerability Type: Argument injection caused by unsafe string interpolation
Risk Level: HighVulnerable Code
python def substitute_vars(text, variables): """Replace {var_name} placeholders with actual values. SECURITY: {env.*} access is BLOCKED to prevent environment variable leakage. Only workflow-defined variables are substituted. """ def replacer(match): key = match.group(1) if key.startswith("env."): # BLOCKED: env var access via workflow variables is a credential leak vector return "{" + key + "}" value = variables.get(key) if value is None: return match.group(0) return str(value) return re.sub(r'\{(\w[\w.]*)\}', replacer, text)python def run_step(step, variables, dry_run=False): """Execute a single workflow step.""" name = step.get("name", "unnamed") command = substitute_vars(step.get("command", ""), variables) on_fail = step.get("on_fail", "abort") condition = step.get("condition") save_output = step.get("save_output") timeout = step.get("timeout", 60) max_retries = 3 if on_fail == "retry" else 1 # Check condition if condition and not check_condition(condition, variables): print(f" SKIP [{name}] — condition not met: {condition}") return True, None # Validate command after substitution valid, reason = _validate_command(command) if not valid: print(f" BLOCKED [{name}] {reason}") return False, None if dry_run: print(f" [DRY] [{name}] {command}") return True, None for attempt in range(max_retries): if attempt > 0: print(f" RETRY [{name}] attempt {attempt + 1}/{max_retries}") time.sleep(2) pr ...[truncated 2771 chars]- Remediation
View remediation
Remediation Suggestions
- Define commands as arrays of arguments rather than shell-like strings, for example
["program", "--input", "{result}"]. - Perform substitution independently within each array element so one substituted value cannot create additional arguments.
- Treat all saved command output as untrusted.
- Require structured output, such as validated JSON, and expose only explicitly selected fields to subsequent steps.
- Apply per-variable schemas, length limits, and allowlists for expected formats such as paths, identifiers, or enumeration values.
- Where a value may begin with
-, use the target application's end-of-options marker (--) when supported. - Add tests covering whitespace, quotation marks, leading option prefixes, embedded newlines, and multi-argument payloads.
- Define commands as arrays of arguments rather than shell-like strings, for example
