T09 · Insecure Skill Coding Practices
- Location
scripts/manage_preferences.py:37- Finding
Plaintext Storage of Sensitive Employee, Location, and Calendar Metadata
- Content
View full analysis
Vulnerability Details
File Locations:
scripts/manage_preferences.py:37-39scripts/manage_preferences.py:45-54scripts/manage_preferences.py:84-93scripts/watch_waitlist.py:57-59scripts/watch_waitlist.py:88-100scripts/workspace_manager.py:38-41
Vulnerability Type: Sensitive data stored in plaintext with process-default file permissions
Risk Level: MediumVulnerable Code
scripts/manage_preferences.py:37-39:python def save_prefs(data): with open(PREFS_FILE, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)scripts/manage_preferences.py:45-54:python prefs[user_id] = { "default_building": args.building or "", "capacity_gte": args.capacity_gte or 0, "capacity_lte": args.capacity_lte or 999, "preferred_rooms": [r.strip() for r in args.preferred_rooms.split(",")] if args.preferred_rooms else [], "note": args.note or "", "selection_history": prefs.get(user_id, {}).get("selection_history", []) } save_prefs(data)scripts/manage_preferences.py:84-93:python history = user_prefs.setdefault("selection_history", []) history.append({ "room": room_name, "building": building_name, "time": __import__("datetime").datetime.now().isoformat() }) # Retain only the latest 20 entries user_prefs["selection_history"] = history[-20:]scripts/watch_waitlist.py:57-59:python def save_waitlist(data: WaitlistData) -> None: with open(WAITLIST_FILE, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)scripts/watch_waitlist.py:88-100:python pending.append({ "event_id": event_id, "summary": args.summary or "", "start": args.start, "end": args.end, "building": args.building or "", "capacity_gte": args.capacity_gte or 0, "attempted_rooms": [], "atte ...[truncated 3016 chars]- Remediation
View remediation
Remediation Suggestions
- Move mutable state out of the Skill package and into a per-user application-data directory.
- Create the state directory with mode
0700and each state file with mode0600, independent of the process umask. - Use atomic writes through a temporary owner-only file followed by
os.replaceto prevent partial writes and unsafe permission transitions. - Separate records by authenticated user or tenant instead of aggregating all users in one preference file.
- Enforce authorization before reading, listing, modifying, or deleting another user's records.
- Minimize retained data. Avoid storing meeting summaries, stable event identifiers, notes, or precise location history unless operationally necessary.
- Define retention periods and automatically purge expired waitlist entries and old room-selection or workspace history.
- Where the local threat model requires protection from filesystem disclosure, encrypt sensitive fields using an OS keyring or a tenant-scoped key stored outside the project directory.
- Document the sensitivity and lifecycle of all generated files and ensure backups and logs apply equivalent access controls.
