T09 · Insecure Skill Coding Practices
- Location
skill_runner.py:35- Finding
Caller-Controlled Configuration Enables Arbitrary Local Program Execution and Process Termination
- Content
View full analysis
Vulnerability Details
File Location:
skill_runner.py:35-83;cad_launcher.py:58-73, 257-268, 327-359, 433-499
Vulnerability Type: Caller-controlled security-sensitive configuration
Risk Level: HighVulnerable Code
python if skill == "launch_app": result = launch_app( app=args.get("app", ""), config_file=args.get("config_file", "config.json") )python elif skill == "close_app": result = close_app( app=args.get("app", ""), config_file=args.get("config_file", "config.json"), force=args.get("force", True) )python def load_config(config_file: str = CONFIG_FILE) -> Dict[str, Any]: if not os.path.isfile(config_file): return fail(f"配置文件不存在: {config_file}") try: with open(config_file, "r", encoding="utf-8") as f: cfg = json.load(f) return ok(config=cfg) except Exception as e: return fail(f"读取配置文件失败: {e}")python def find_executable(app: str, config: Dict[str, Any]) -> Optional[str]: app_info = get_app_info(app, config) if not app_info: return None for p in app_info.get("saved_paths", []): if os.path.isfile(p): return p for p in app_info.get("candidate_paths", []): if os.path.isfile(p): return p return Nonepython def launch_app(app: str, config_file: str = CONFIG_FILE) -> Dict[str, Any]: app_check = validate_app(app) if not app_check["success"]: return app_check app = app_check["app"] cfg = load_config(config_file) if not cfg["success"]: return cfg config = cfg["config"] exe_path = find_executable(app, config) if not exe_path: detect_result = detect_app_path(app, config_file=config_file) if detect_result["success"]: exe_path = detect_result ...[truncated 3234 chars]- Remediation
View remediation
Remediation Suggestions
- Remove
config_filefrom caller-controlled skill arguments. - Resolve the configuration from a fixed, skill-owned path derived from
__file__, rather than the current working directory. - If configuration selection is required, canonicalize it with
os.path.realpath()and verify that it remains inside an approved directory. - Reject absolute paths, traversal components, network paths, and reparse-point escapes.
- Treat packaged candidate paths and process-name allowlists as immutable application metadata.
- Validate executable paths against application-specific expected filenames and approved installation roots.
- Validate process names against a hardcoded mapping rather than values from a selectable JSON file.
- Run the skill under a restricted operating-system account and prevent it from terminating privileged or unrelated processes.
- Add security tests proving that external configuration files cannot select arbitrary executable paths or process names.
- Remove
