T09 · Insecure Skill Coding Practices
Note
- Location
- src/reading_database/connection.py:9
- Finding
- Local SQLite Database Is Created Without Explicit Owner-Only Permissions<![CDATA[ ## Vulnerability Details **File Location**: `src/reading_database/connection.py:9-22` **Vulnerability Type**: Insecure local file permissions **Risk Level**: Low ```python DATA_DIR = Path.home() / ".config" / "reading-manager" DB_PATH = DATA_DIR / "reading.db" def init_data_dir(): DATA_DIR.mkdir(parents=True, exist_ok=True) def get_connection(): init_data_dir() conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row return conn ``` ### Technical Analysis The application creates its data directory and SQLite database without assigning explicit owner-only permissions. Consequently, the effective permissions depend on the runtime environment's `umask`. The database contains personal reading information, notes, history, stored source URLs, and configuration fields intended for API keys. On a shared system with permissive filesystem defaults, another local user may be able to read or copy the database. The vulnerability does not provide remote access by itself and requires an existing local account with sufficient filesystem traversal permissions. ### Attack Path 1. The victim runs a `reading` command, causing `init_data_dir()` and `sqlite3.connect()` to create the directory and database. 2. The process creates these resources using permissions derived from the current `umask`. 3. A local attacker checks the permissions of `~/.config/reading-manager/reading.db`. 4. If the file and parent directories permit access, the attacker opens or copies the SQLite database. 5. The attacker extracts personal reading records, notes, stored URLs, user configuration, or any API keys subsequently stored in the configuration table. ### Impact Assessment Successful exploitation may disclose all information stored in the database to another local user. This can include private notes, reading activity, article URLs, identity-related configuration, and plaintext API credentials if configured. The issue does not grant elevated operating- ...[truncated 162 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Create the data directory with owner-only permissions: ```python def init_data_dir(): DATA_DIR.mkdir(parents=True, exist_ok=True, mode=0o700) DATA_DIR.chmod(0o700) ``` 2. Enforce owner-only permissions on the database immediately after opening or creating it: ```python def get_connection(): init_data_dir() conn = sqlite3.connect(DB_PATH) DB_PATH.chmod(0o600) conn.row_factory = sqlite3.Row return conn ``` 3. Apply equivalent protection to SQLite auxiliary files, including journal, WAL, and shared-memory files. A restrictive process `umask`, such as `0o077`, should be established while creating database resources. 4. Validate and repair permissions for existing installations during startup rather than protecting only newly created files. 5. Avoid storing API keys in plaintext SQLite fields where possible. Use an operating-system credential store or keyring and keep only a non-sensitive reference in the database. 6. Add automated tests verifying that the data directory is not accessible by group or other users and that the database has mode `0600`. ]]>
