T09 · Insecure Skill Coding Practices
- Location
scripts/collection_pipeline/utils.py:326- Finding
Caller-Controlled Python Script Paths Permit Arbitrary Local Code Execution
- Content
View full analysis
None: """Write absolute downstream script paths; retain an existing path if its file exists.""" for script_key in ( "textgen_script", "imagegen_script", "brand_gene_save_script", "run_one_task_script", ): resolved = scripts[script_key] existing = job.get(script_key) if existing and os.path.isfile(os.path.abspath(str(existing))): job[script_key] = os.path.abspath(str(existing)) else: job[script_key] = resolved ``` The dispatch phase subsequently executes the preserved `run_one_task_script` path in `scripts/collection_pipeline/runner.py:60-72`: ```python with open(args.state, encoding="utf-8") as f: state = json.load(f) total = len(state["task_specs"]) run_script = state["run_one_task_script"] saved_re = re.compile(r"Saved full response:\s*(.+?)\s*$", re.M) def run_one(i): # capture: child-task output is not forwarded to dispatch stdout proc = subprocess.run( [sys.executable, run_script, "--state", args.state, "--index", str(i)], text=True, capture_output=True, ) ``` The per-task executor also executes job-derived text-generation and image-generation scripts in `scripts/collection_pipeline/single_task.py:87-113`: ```python def _run_textgen(textgen_script: str, params: dict, task_id: str) -> str: """Invoke the official text-generation script and return gener ...[truncated 4082 chars]- Remediation
View remediation
str: candidate = os.path.realpath(path) root = os.path.realpath(trusted_root) if os.path.commonpath([candidate, root]) != root: raise ValueError("Script is outside the trusted Skill directory") if not os.path.isfile(candidate): raise FileNotFoundError(candidate) if os.path.islink(path): raise ValueError("Symbolic-link script paths are not permitted") return candidate ``` 4. Restrict each field to its exact expected file, rather than merely an expected directory. For example, `run_one_task_script` should always resolve to this Skill's packaged `scripts/run_one_task.py`. 5. If deployment flexibility is required, place trusted script mappings in administrator-controlled configuration rather than user/job JSON. 6. Protect state files from tampering by using restrictive permissions, validating ownership, and optionally signing security-sensitive fields. 7. Add tests proving that absolute paths, relative traversal paths, symlinks, and modified state files cannot select alternative executables. ]]>
