T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/task_manager.py:16
- Finding
- Missing Task Ownership and Caller Isolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/task_manager.py`, lines 16-77 **Vulnerability Type**: Missing authorization and tenant isolation **Risk Level**: High ### Complete Code Snippet ```python SKILL_DIR = Path(__file__).parent.parent TASKS_FILE = SKILL_DIR / "tasks.json" def load_tasks(): if TASKS_FILE.exists(): with open(TASKS_FILE, "r", encoding="utf-8") as f: return json.load(f) return [] def save_tasks(tasks): with open(TASKS_FILE, "w", encoding="utf-8") as f: json.dump(tasks, f, indent=2) def cmd_add(text): tasks = load_tasks() task_id = len(tasks) + 1 tasks.append({"id": task_id, "text": text.strip(), "done": False}) save_tasks(tasks) print(f"✅ Task added (#{task_id}): {text.strip()}") def cmd_list(): tasks = load_tasks() if not tasks: print("📋 No tasks yet. Say 'add task <description>' to create one.") return lines = ["**📋 Your Tasks:**"] for t in tasks: status = "✅" if t["done"] else "⬜" lines.append(f" {status} `[{t['id']}]` {t['text']}") print("\n".join(lines)) def cmd_complete(task_id): tasks = load_tasks() task = next((t for t in tasks if t["id"] == int(task_id)), None) if not task: print(f"❌ Task #{task_id} not found.") return task["done"] = True save_tasks(tasks) # Remove completed task tasks = [t for t in tasks if not (t["id"] == int(task_id))] save_tasks(tasks) print(f"✅ Task #{task_id} completed and removed: {task['text']}") def cmd_delete(task_id): tasks = load_tasks() task = next((t for t in tasks if t["id"] == int(task_id)), None) if not task: print(f"❌ Task #{task_id} not found.") return tasks = [t for t in tasks if t["id"] != int(task_id)] save_tasks(tasks) print(f"🗑️ Task #{task_id} deleted: {task['text']}") ``` ### Technical Analysis All commands read from and write to the same `tasks.json` file ...[truncated 1556 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Pass trusted Discord context separately from user-controlled command text, including the authenticated user ID, guild ID, and channel ID. 2. Add explicit ownership and scope fields to each task, for example: ```python { "id": task_id, "owner_id": discord_user_id, "guild_id": discord_guild_id, "channel_id": discord_channel_id, "text": text, "done": False } ``` 3. Filter task listings by the authenticated owner and the intended guild/channel scope. 4. Before completing or deleting a task, retrieve it by both task ID and owner/scope rather than by task ID alone. 5. Do not accept identity fields from natural-language command content. Obtain them from trusted integration metadata. 6. Use globally unique identifiers or owner-scoped counters instead of `len(tasks) + 1`, which can produce duplicate IDs after deletion. 7. Add tests proving that one user cannot list, complete, or delete another user's tasks. 8. If shared task lists are intentional, define roles and enforce explicit read/write permissions for each shared list. ]]>
