T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/qmt_autopilot.py:9
- Finding
- Environment-Controlled Arbitrary Python Module Execution## Vulnerability Details **File Location**: `scripts/qmt_autopilot.py`, lines 9–19 and 27 **Vulnerability Type**: Untrusted dynamic module loading **Risk Level**: High ### Vulnerable Code ```python PLANNER_PATH = os.getenv( "STRATEGY_PLANNER_PATH", "/opt/production_ready_skills/qmt-strategy-planner-skill/scripts/strategy_planner.py" ) def load_planner(): spec = importlib.util.spec_from_file_location( "qmt_strategy_planner_cli", PLANNER_PATH ) if spec is None or spec.loader is None: raise RuntimeError(f"无法加载策略规划器: {PLANNER_PATH}") mod = importlib.util.module_from_spec(spec) sys.modules[spec.name] = mod spec.loader.exec_module(mod) return mod ``` ```python planner = load_planner() ``` ### Technical Analysis The script obtains `PLANNER_PATH` directly from the `STRATEGY_PLANNER_PATH` environment variable and executes the specified Python file through `exec_module()`. It does not constrain the path to a trusted directory, resolve and validate symlinks, verify file ownership or permissions, or authenticate the module with a pinned cryptographic hash. Python module initialization executes top-level statements. Consequently, loading the configured file is itself a code-execution operation, regardless of which `plan`, `clarify`, or `run` command is requested. The module is also loaded before command validation and dispatch. The default external planner dependency is documented, but the environment-controlled override is not disclosed in the project documentation. Because the referenced planner is outside this artifact, its behavior could not be audited here. ### Attack Path 1. An attacker gains the ability to set or influence environment variables for the Skill process. 2. The attacker creates or identifies a malicious Python file readable by that process. 3. The attacker sets `STRATEGY_PLANNER_PATH` to the malicious file's path. 4. A user or automation invokes `qmt_autopilot.py` with any supported o ...[truncated 1176 chars]
- Remediation
- ## Remediation Suggestions 1. Remove the `STRATEGY_PLANNER_PATH` environment override and import a packaged, version-pinned planner dependency from a fixed trusted location. 2. If runtime path configuration is essential: - Maintain an explicit allowlist of approved canonical paths. - Resolve the path with `realpath()` before validation. - Reject paths outside a dedicated trusted root. - Reject symlinks or verify their resolved targets. - Verify that the file and parent directories are owned by an expected privileged account and are not writable by untrusted users. - Verify the module against a pinned cryptographic hash or signed manifest before loading it. 3. Validate the command before loading the planner so invalid commands cannot trigger external module execution. 4. Run the Skill under a dedicated least-privileged account with only the brokerage and filesystem permissions required for its task. 5. Separate simulated and live execution credentials and require an explicit, independently validated authorization step for live trading. 6. Document every executable external dependency and configuration override so the deployed execution boundary can be reviewed. 7. Fail closed when any path, ownership, permission, or integrity check fails.
