T09 · Insecure Skill Coding Practices
- Location
database.py:19- Finding
Sensitive mental-health data is stored in plaintext despite explicit encryption claims
- Content
View full analysis
Vulnerability Details
File Location:
database.py:19-28,database.py:33-55,database.py:62-76,database.py:81-99, anddatabase.py:132-150
Related Misleading Claims:README.md:23,README.md:40, andsignet-mind.py:37
Vulnerability Type: Plaintext storage of sensitive information and ineffective encryption implementation
Risk Level: HighVulnerable Code
python def get_encryption_key() -> str: """Get or generate encryption key for local data.""" if ENCRYPTION_KEY_FILE.exists(): return ENCRYPTION_KEY_FILE.read_text().strip() # Generate new key (in production, this would be derived from user password) key = os.urandom(32).hex() ENCRYPTION_KEY_FILE.write_text(key) os.chmod(ENCRYPTION_KEY_FILE, 0o600) return keyThe generated key is not used when creating or accessing either database:
python def init_conversation_db(): """Initialize the conversations database.""" conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS conversations ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, user_message TEXT NOT NULL, ai_response TEXT NOT NULL, mood_before TEXT, mood_after TEXT, tags TEXT ) """) cursor.execute(""" CREATE TABLE IF NOT EXISTS user_profile ( key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at TEXT NOT NULL ) """) conn.commit() conn.close()Conversation content is inserted directly into ordinary SQLite columns:
python def save_conversation(user_msg: str, ai_msg: str, mood_before: Optional[str] = None, mood_after: Optional[str] = None, tags: Optional[List[str]] = None): """Save ...[truncated 3686 chars]- Remediation
View remediation
Remediation Suggestions
- Replace standard plaintext SQLite storage with a reviewed encrypted database solution that provides authenticated encryption.
- Ensure encryption is actually applied to the database or to every sensitive field before insertion. Do not treat key generation alone as encryption.
- Store or protect the encryption key using the operating system credential store. If password-derived keys are supported, use a modern password-based key derivation function with a unique salt and appropriate cost settings.
- Apply restrictive permissions to
DATA_DIR,conversations.db,mood.db, their journal or WAL files, and any temporary database files. - Account for SQLite side files such as
-wal,-shm, and journals, which may otherwise retain plaintext records. - Add automated tests that insert a unique sensitive marker and verify that it cannot be found in the raw database or associated files.
- Define a migration procedure for existing plaintext databases, securely replacing old files after encrypted migration where the platform permits.
- Until effective encryption is implemented and verified, remove all statements claiming that records are encrypted and clearly inform users that storage is plaintext.
