T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/merge_abilities.py:10
- Finding
- Predictable Shared Temporary File Allows Ability Database Poisoning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/merge_abilities.py`, lines 10-12, 25-26, and 73-74 **Vulnerability Type**: Unsafe predictable temporary file and unvalidated data ingestion **Risk Level**: Medium ### Vulnerable Code ```python DOTABASE_FILE = '/tmp/dotabase_abilities.json' OUTPUT_FILE = '/root/.openclaw/workspace/magi/skills/dota2-coach/scripts/abilities_db.json' HEROES_FILE = '/root/.openclaw/workspace/magi/skills/dota2-coach/scripts/heroes_db.json' ``` ```python # Load dotabase abilities with open(DOTABASE_FILE) as f: dotabase = json.load(f) ``` ```python with open(OUTPUT_FILE, 'w') as f: json.dump(result, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis The script consumes `/tmp/dotabase_abilities.json`, a fixed and predictable path in a globally shared temporary directory. It does not verify the source file's ownership, permissions, type, provenance, or symbolic-link status. It also performs no schema or integrity validation before using the records to construct the persistent ability database. A local user who can create or replace this path may supply attacker-controlled JSON before a more privileged user runs the script. The script then incorporates that content into `abilities_db.json`. The fixed output path under `/root/.openclaw` makes the issue more consequential when the script is run with elevated privileges. The direct write to the destination is also non-atomic. Interruption during serialization can leave the database truncated or partially written. ### Attack Path 1. A local attacker creates or replaces `/tmp/dotabase_abilities.json` with syntactically valid but malicious or misleading ability records. 2. The attacker waits for an operator or automated process to run `scripts/merge_abilities.py`. 3. The script opens the predictable temporary file without checking its owner, permissions, symlink status, or integrity. 4. The attacker-controlled records are grouped and copied into the generat ...[truncated 1017 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Eliminate the fixed shared temporary filename. Use `tempfile.NamedTemporaryFile` or `tempfile.TemporaryDirectory` with permissions restricted to the current user. 2. Resolve database destinations relative to the script rather than using a hard-coded root workspace: ```python SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) OUTPUT_FILE = os.path.join(SCRIPT_DIR, "abilities_db.json") HEROES_FILE = os.path.join(SCRIPT_DIR, "heroes_db.json") ``` 3. If an externally supplied source path is necessary, require it as an explicit command-line argument and reject symbolic links or non-regular files. 4. Verify that the source file is owned by the expected user and is not writable by unrelated users. 5. Validate the JSON against a strict schema, including allowed field types, required identifiers, maximum string lengths, and expected hero IDs. 6. Verify downloaded data provenance with a pinned digest or authenticated source before merging it. 7. Write the generated database to a same-directory temporary file, flush and `fsync` it, and replace the destination atomically with `os.replace`. 8. Run the update process with the least-privileged account that can write only to the Skill's data directory. ]]>
