T09 · Insecure Skill Coding Practices
- Location
scripts/tax_docs.py:124- Finding
Sensitive Tax Records Stored Without Restrictive File Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/tax_docs.py, lines 37 and 124–139
Vulnerability Type: Plaintext sensitive-data storage with ambient file permissions
Risk Level: MediumVulnerable Code
python DB_PATH = os.path.expanduser("~/.tax_docs.json")python def load_db(): if os.path.exists(DB_PATH): with open(DB_PATH, "r") as f: return json.load(f) return { "bracket": 22, "expenses": [], "mileage": [], "home_office": None, } def save_db(db): with open(DB_PATH, "w") as f: json.dump(db, f, indent=2, default=str)Technical Analysis
The application stores its database in the plaintext file
~/.tax_docs.json. This database can contain sensitive financial and personal information, including tax bracket, transaction amounts, merchants, dates, expense notes, mileage purposes, charitable activity, medical expense categories, and home-office details.The file is created using Python's ordinary
open(..., "w")operation. Its permissions therefore depend on the process's ambientumask; the application neither requests an owner-only mode nor repairs insecure permissions on an existing database. On a system with a permissiveumask, or where the file was pre-created with broad permissions, another local user may be able to read the stored records.The same direct write also truncates and rewrites the live database rather than using a securely permissioned temporary file followed by an atomic replacement. Although the confirmed confidentiality issue is the lack of enforced permissions, atomic replacement would additionally improve integrity and crash safety.
Attack Path
- A user invokes a data-changing command such as
setup,add,add-mileage, oradd-home-office. - The command passes the in-memory database to
save_db(). save_db()creates or rewrites~/.tax_docs.jsonusing permissions derived from the current environment, wit ...[truncated 1107 chars]
- A user invokes a data-changing command such as
- Remediation
View remediation
Remediation Suggestions
- Create the database with explicit owner-only permissions (
0600) rather than relying on the ambientumask. - Check and repair permissions on every load or save so that pre-existing broadly readable files are also protected.
- Store the file inside a private application directory with mode
0700. - Write updates to a securely created temporary file in the same directory, flush and synchronize it, and atomically replace the database to reduce corruption and link-race risks.
- Reject symbolic links or otherwise verify that the destination is a regular file owned by the current user.
- Consider encryption at rest if the threat model includes privileged local users, stolen backups, or offline disk access; restrictive file permissions alone do not protect against those threats.
- Clearly document that the database contains sensitive financial data and is otherwise stored in plaintext.
A secure implementation should use low-level creation with mode
0600, such asos.open()with appropriate creation flags, and applyos.chmod(DB_PATH, 0o600)to existing databases after validating ownership and file type.- Create the database with explicit owner-only permissions (
