T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/mx_self_select.py:144
- Finding
- Financial account data is written with ambient filesystem permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mx_self_select.py`, lines 144–164 and 187–190 **Vulnerability Type**: Sensitive data stored with non-restrictive default permissions **Risk Level**: Medium ### Vulnerable Code ```python with open(csv_path, "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for row in csv_rows: writer.writerow(row) # Save raw JSON json_path = output_dir / f"mx_self_select_{safe_filename(safe_name)}_raw.json" with open(json_path, "w", encoding="utf-8") as f: json.dump(result, f, ensure_ascii=False, indent=2) print(f"\n✅ CSV 已保存: {csv_path}") print(f"📄 原始JSON: {json_path}") ``` The destination directory is also created without an explicit restrictive mode: ```python default_output = Path("/root/.openclaw/workspace/mx_data/output") output_dir = Path(args.output_dir) if args.output_dir else default_output output_dir.mkdir(parents=True, exist_ok=True) ``` ### Technical Analysis The Skill stores a user's financial watchlist in both CSV and raw JSON files. Neither the output directory nor the files are created with explicit owner-only permissions. Their effective permissions therefore depend on the process umask. Under a common umask of `0022`, newly created directories can be mode `0755` and files can be mode `0644`. Consequently, other local accounts may be able to read the watchlist and any additional fields included in the complete API response. The use of ordinary `open(..., "w")` also follows symbolic links and truncates existing targets. If an untrusted local user can modify the selected output directory, that user could potentially redirect a write to another file writable by the Skill process. ### Attack Path 1. A user runs the Skill and authenticates with `MX_APIKEY`. 2. The Skill retrieves account-specific watchlist data from the Eastmoney API. 3. It creates the output directory and writes CSV and raw JSON files us ...[truncated 1078 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Create the output directory with owner-only permissions and verify its final mode: ```python output_dir.mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(output_dir, 0o700) ``` - Create output files atomically with mode `0600`, such as through `os.open` using `O_CREAT | O_EXCL | O_WRONLY` and `0o600`. - Reject symbolic links and verify that the resolved destination remains inside the intended output directory. - Use a temporary file in the same protected directory, flush and synchronize it, and then atomically rename it into place. - Consider making raw JSON retention opt-in because it may contain more information than the formatted CSV. - Validate user-supplied `--output-dir` paths and document that the destination must not be shared or writable by untrusted users. ]]>
