T09 · Insecure Skill Coding Practices
- Location
scripts/validate_skill.py:169- Finding
Static Validator Executes Python Files from an Untrusted Target Package
- Content
View full analysis
Vulnerability Details
File Location:
scripts/validate_skill.py, lines 169–194
Vulnerability Type: Arbitrary local code execution during package validation
Risk Level: HighVulnerable Code
python def validate_scripts(root: Path, errors: list[str], warnings: list[str]) -> list[dict[str, Any]]: results: list[dict[str, Any]] = [] scripts_dir = root / "scripts" if not scripts_dir.exists(): return results for script in sorted(scripts_dir.glob("*.py")): try: proc = subprocess.run( [sys.executable, str(script), "--help"], cwd=str(root), text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=10, ) except subprocess.TimeoutExpired: errors.append(f"{script.relative_to(root)} --help timed out.") results.append({"script": str(script.relative_to(root)), "help_ok": False, "reason": "timeout"}) continue ok = proc.returncode == 0 and "usage" in proc.stdout.lower() if not ok: errors.append(f"{script.relative_to(root)} --help failed or did not print usage.")The execution is enabled through the caller-controlled validation option:
python root = Path(args.path).resolve() ... script_results = validate_scripts(root, errors, warnings) if args.check_scripts else []Technical Analysis
The validator accepts an arbitrary package root and, when
--check-scriptsis supplied, discovers every*.pyfile beneath that root'sscripts/directory and invokes it with the current Python interpreter.Supplying
--helpdoes not make this operation safe. Python executes module-level statements before a script processes command-line arguments. Consequently, an attacker-controlled script can execute an arbitrary payload before displaying help, exiti ...[truncated 1903 chars]- Remediation
View remediation
Remediation Suggestions
- Remove runtime execution from static validation. Do not invoke package scripts merely to verify their help output.
- Parse Python files with
ast.parse()to validate syntax without executing module-level statements. - Inspect
argparseusage statically where practical, or treat help-output testing as a separate operation that is disabled for untrusted packages. - If execution is operationally necessary, require an explicit trusted-package flag and display a clear warning that arbitrary code will run.
- Execute runtime checks inside a hardened sandbox with:
- No inherited credentials or sensitive environment variables.
- No network access.
- A read-only package mount.
- No writable host directories.
- A dedicated unprivileged user.
- Process, memory, and execution-time limits.
- Restrictions on child-process creation where supported.
- In automated review systems, separate static inspection from post-approval runtime testing and never run unreviewed scripts on a privileged CI worker.
