T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/financial_inventory.py:10
- Finding
- Sensitive Divorce and Financial Data Stored and Exposed in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `scripts/financial_inventory.py`, lines 10-57 **Vulnerability Type**: Plaintext sensitive-data storage and exposure through command-line arguments and standard output **Risk Level**: Medium ### Vulnerable Code ```python DIVORCE_DIR = os.path.expanduser("~/.openclaw/workspace/memory/divorce") def ensure_dir(): os.makedirs(DIVORCE_DIR, exist_ok=True) def main(): parser = argparse.ArgumentParser(description='Build financial inventory') parser.add_argument('--type', required=True, choices=['asset', 'debt', 'account', 'property', 'retirement'], help='Type of financial item') parser.add_argument('--description', required=True, help='Description') parser.add_argument('--value', type=float, help='Current value') parser.add_argument('--joint', action='store_true', help='Jointly owned') args = parser.parse_args() item_id = f"FIN-{str(uuid.uuid4())[:6].upper()}" item = { "id": item_id, "type": args.type, "description": args.description, "value": args.value, "joint": args.joint, "added_at": datetime.now().isoformat() } # Load and save inventory_file = os.path.join(DIVORCE_DIR, "financial_inventory.json") data = {"items": []} if os.path.exists(inventory_file): with open(inventory_file, 'r') as f: data = json.load(f) data['items'].append(item) ensure_dir() with open(inventory_file, 'w') as f: json.dump(data, f, indent=2) print(f"✓ Financial item logged: {item_id}") print(f" Type: {args.type}") print(f" Description: {args.description}") if args.value: print(f" Value: ${args.value:,.2f}") print(f" Joint: {'Yes' if args.joint else 'No'}") ``` ### Technical Analysis The script processes highly sensitive divorce and financial information, including asset description ...[truncated 2702 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Enforce restrictive filesystem permissions** - Create the storage directory with owner-only permissions such as `0700`. - Create the inventory file with mode `0600`. - Inspect and correct permissions on existing directories and files rather than relying on the current umask. - Reject symbolic links and verify that the resolved destination remains inside the expected storage directory. 2. **Encrypt sensitive records** - Protect the JSON content with authenticated encryption. - Store encryption keys in an operating-system keychain or another dedicated secret store, not alongside the encrypted data. - If encrypted filesystem storage remains an external prerequisite, clearly disclose that limitation and verify the protection where practical rather than claiming it is enforced by the skill. 3. **Avoid command-line exposure** - Collect sensitive descriptions and values through protected interactive input, standard input, or a file descriptor with restrictive permissions. - Do not place private financial information in command-line arguments that may be retained in shell history or exposed through process inspection. 4. **Minimize output disclosure** - Do not print descriptions or exact values by default. - Return only the generated record identifier and a success message. - Require an explicit option to display sensitive details and warn that output may be logged. 5. **Use atomic, secure file updates** - Write updates to an owner-only temporary file in the same protected directory. - Flush and synchronize the content before atomically replacing the destination. - Preserve restrictive permissions during replacement and safely handle malformed or corrupted existing data. 6. **Reduce stored data** - Collect only fields required for the stated workflow. - Provide documented retention, export, and secure-deletion controls appropriate for sensitive divorce records. ]]>
