T09 · Insecure Skill Coding Practices
- Location
scripts/health-reminder.py:9- Finding
Health Data Stored in Plaintext Without Explicitly Restrictive Filesystem Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/health-reminder.py, lines 9-36
Vulnerability Type: Plaintext sensitive-data storage with insecure file permissions
Risk Level: MediumVulnerable Code
python DATA_DIR = Path.home() / ".health-reminder" MED_FILE = DATA_DIR / "medications.json" WATER_FILE = DATA_DIR / "water.json" ACTIVITY_FILE = DATA_DIR / "activity.json" def init_data(): """Initialize data files""" DATA_DIR.mkdir(parents=True, exist_ok=True) for f in [MED_FILE, WATER_FILE, ACTIVITY_FILE]: if not f.exists(): with open(f, 'w') as f: json.dump([] if 'med' in str(f) or 'activity' in str(f) else {}, f) def load_meds(): init_data() with open(MED_FILE, 'r') as f: return json.load(f) def save_meds(meds): with open(MED_FILE, 'w') as f: json.dump(meds, f, indent=2) def load_water(): init_data() with open(WATER_FILE, 'r') as f: return json.load(f) def save_water(water): with open(WATER_FILE, 'w') as f: json.dump(water, f, indent=2)Technical Analysis
The application stores medication names, medication schedules, creation timestamps, and timestamped water-intake records as unencrypted JSON files under
~/.health-reminder.The directory and files are created without explicit permission modes. Their effective permissions therefore depend on the process umask and any pre-existing filesystem objects. Under a commonly used umask such as
022, the directory may be created as0755and files as0644, allowing other local users to read the health records.The code also opens existing paths directly without verifying file type, ownership, permissions, or whether a path is a symbolic link. If an attacker can write to or pre-create the data directory—for example, because of unusually permissive home-directory permissions, shared execution contexts, or prior ...[truncated 2141 chars]
- Remediation
View remediation
Remediation Suggestions
-
Create the data directory with owner-only permissions and correct permissions on existing directories:
python DATA_DIR.mkdir(parents=True, exist_ok=True, mode=0o700) DATA_DIR.chmod(0o700) -
Create data files with mode
0600rather than relying on the process umask. Useos.open()with restrictive flags and permissions, then wrap the descriptor withos.fdopen(). -
Refuse symbolic links and unexpected file types. Where supported, use
O_NOFOLLOW; otherwise inspect paths withlstat()immediately before opening them. Verify that each path is a regular file owned by the current user. -
Correct permissions on existing files before reading or writing them, and fail safely if ownership is unexpected rather than silently trusting the path.
-
Use atomic writes: write to a securely created temporary file in the protected directory, flush and synchronize it, set mode
0600, and atomically replace the destination after validating it. -
Consider encrypting stored health records when the threat model includes privileged local readers, backups, or filesystem disclosure. Keep encryption keys separate from the data and protect them with an operating-system credential store.
-
Document the local storage location, retained health information, permissions, and deletion procedure so users can make an informed privacy decision.
-
