T09 · Insecure Skill Coding Practices
Warning
- Location
- crm.py:54
- Finding
- Plaintext CRM records stored without enforced restrictive file permissions<![CDATA[ ## Vulnerability Details **File Location**: `crm.py:54-62`; sensitive records are present in `crm.json:1-368` **Vulnerability Type**: Plaintext sensitive-data storage and insufficient file-permission enforcement **Risk Level**: Medium ### Vulnerable Code ```python def load(): if not os.path.exists(CRM_FILE): return [] with open(CRM_FILE) as f: return json.load(f) def save(leads): with open(CRM_FILE, "w") as f: json.dump(leads, f, indent=2) ``` An example of the data exposed in `crm.json:20-40` is: ```json { "id": 2, "name": "P.A.C. Plumbing", "phone": "718-720-4980", "category": "hvac", "status": "interested", "calls": [ { "date": "2026-02-27", "outcome": "interested", "notes": "" } ], "notes": [ "Owner is Paul, best time is morning before 9am" ], "followup_date": "2026-03-03", "added": "2026-02-27" } ``` ### Technical Analysis The application stores lead names, telephone numbers, sales statuses, contact histories, follow-up dates, and free-form notes directly in an unencrypted JSON file. The project also distributes a populated copy of that file. The `save()` function opens `crm.json` without explicitly applying restrictive permissions. When the file is created, its effective permissions are determined by the process umask. In an environment with a permissive umask, other local users may be able to read the CRM data. The application does not subsequently verify or correct the file mode. Because the data file resides within the project directory, it may also be committed, copied, archived, or distributed with the Skill. Repository recipients do not need to run the application or bypass authentication to read the records. ### Attack Path 1. An attacker obtains read access to the project directory through local multi-user access, an exposed archive, repository access, backup access, or accidental project distribution. 2. The attacker locates `crm.json` in ...[truncated 1071 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove operational CRM records from the distributed Skill and replace `crm.json` with an empty array or clearly synthetic sample data. 2. Add `crm.json` to `.gitignore` and store live CRM data outside the source or Skill directory. 3. If real records were committed, assess the exposure and purge them from repository history where appropriate. Rotate or invalidate any sensitive information that can be changed. 4. Create the data file with owner-only permissions, such as mode `0600`, and verify permissions before every read and write. 5. Use atomic writes through a temporary file created with restrictive permissions, then replace the destination file to reduce corruption and permission risks. 6. Restrict access to the parent data directory, preferably with mode `0700`. 7. Consider an encrypted or authenticated datastore when the records contain personal, confidential, or regulated information. 8. Define and enforce data-retention rules for call histories and notes, and warn users not to store secrets or unnecessary sensitive personal information in free-form fields. ]]>
