T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/distribute.py:108
- Finding
- Arbitrary Command Execution Through Untrusted Per-Skill Configuration## Vulnerability Details **File Location**: `scripts/distribute.py:108-118, 378-383, 397-412` **Vulnerability Type**: Untrusted configuration used to select and execute a local command **Risk Level**: High ### Complete Code Snippet ```python def load_config(skill_dir): """Configuration priority: skill-local config, user-global config, defaults.""" config = json.loads(json.dumps(DEFAULT_CONFIG)) local_cfg = Path(skill_dir) / ".skill-distributor" / "config.json" candidates = [] if local_cfg.exists(): candidates.append(local_cfg) if HOME_CONFIG_DIR.joinpath("config.json").exists(): candidates.append(HOME_CONFIG_DIR.joinpath("config.json")) for p in candidates: try: merge_config(config, json.loads(p.read_text(encoding="utf-8-sig"))) except Exception as e: log(f"Warning: failed to read configuration {p}: {e}") return config ``` ```python def publish_skillhub(config, work_dir, tag, dry_run): pcfg = config["platforms"].get("skillhub", {}) if not pcfg.get("enabled", True): return command = pcfg.get("command", "skillhub publish").split() exe = shutil.which(command[0]) if command else None if not exe: log("Skipping SkillHub: CLI not found") return ``` ```python token = load_secret("SKILLHUB_TOKEN") env = dict(os.environ) if token: env["SKILLHUB_TOKEN"] = token args = command[1:] + [str(clean_dir), "--version", tag.lstrip("v")] if token: args += ["--token", token] proc = run_cmd(exe, args, work_dir, env=env) ``` ### Technical Analysis The directory being published can contain `.skill-distributor/config.json`. This untrusted, package-local file has priority over the user-global configuration and can redefine `platforms.skillhub.command`. The first token of that setting is resolved with `shutil.which()`, while all remaining tokens become process arguments. No executable allowlist, trusted-path rest ...[truncated 2056 chars]
- Remediation
- ## Remediation Suggestions - Do not permit a skill-local configuration file to select an executable or command. - Use a fixed, trusted SkillHub executable and fixed publication subcommand. - Move any command customization to a user-owned global configuration outside the skill directory. - If customization is essential, enforce an explicit allowlist of executable names and expected subcommands. - Resolve the executable from a trusted installation path rather than accepting arbitrary `PATH` matches. - Pass a minimal environment to child processes instead of copying all of `os.environ`. - Do not place tokens in command-line arguments, where they may be exposed through process inspection; use a narrowly scoped environment variable or secure credential channel. - Require explicit user confirmation when a non-default publisher executable is selected.
