T09 · Insecure Skill Coding Practices
- Location
scripts/habits.py:68- Finding
Habit Identifier Reuse Causes Silent Data Overwrite and Record Reassignment
- Content
View full analysis
Vulnerability Details
File Location:
scripts/habits.py, lines 68–69; related deletion logic at lines 232–233
Vulnerability Type: Predictable identifier reuse and data-integrity corruption
Risk Level: MediumVulnerable Code
python habit_id = len(data["habits"]) + 1 data["habits"][str(habit_id)] = { "name": name, "goal": goal, "unit": unit, "created": today_str(), "id": habit_id }Related deletion logic:
python del data["habits"][habit_id] data["records"] = [r for r in data["records"] if r.get("habit_id") != habit_id]Technical Analysis
New identifiers are derived from the number of currently stored habits rather than from a monotonic counter, the highest existing identifier, or a collision-resistant value. Deleting any habit other than the one with the highest identifier can create a gap while leaving a higher identifier in use.
A later addition computes
len(data["habits"]) + 1, which can equal an identifier that is still occupied. Assigning the new habit to that dictionary key silently replaces the existing habit. Because records belonging to the overwritten habit are not removed during this replacement, those historical records are subsequently interpreted as belonging to the newly added habit.Attack Path
- Add two habits, producing identifiers
1and2. - Record one or more check-ins for the habit with identifier
2. - Delete the habit with identifier
1. - Add a new habit.
- The identifier calculation returns
2because only one habit remains. - The new habit is written to key
2, silently overwriting the existing habit. - Historical records referencing identifier
2remain and are displayed or reported as records of the new habit.
Impact Assessment
Exploitation requires the ability to invoke the local habit-management commands or otherwise influence the local data workflow. It does not grant additiona ...[truncated 357 chars]
- Add two habits, producing identifiers
- Remediation
View remediation
Remediation Suggestions
Replace count-based identifier generation with one of the following:
- Generate
max(existing_numeric_ids, default=0) + 1. - Store and atomically increment a persistent
next_habit_idcounter. - Use UUIDs for habit identifiers.
Before insertion, explicitly verify that the generated identifier is not already present and fail safely if a collision is detected. Consider validating referential integrity between habits and records during loading and before saving.
Add regression tests covering:
- Adding multiple habits.
- Deleting a non-highest identifier.
- Adding another habit.
- Confirming that no existing habit is overwritten.
- Confirming that historical records remain associated with their original habit.
- Generate
