T09 · Insecure Skill Coding Practices
- Location
scripts/finances.py:14- Finding
Sensitive Financial Data Stored Without Restrictive Filesystem Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/finances.py, lines 14-20 and 28-31
Vulnerability Type: Plaintext sensitive-data storage with permissions inherited from the process environment
Risk Level: MediumVulnerable Code
python DATA_DIR = Path.home() / ".openclaw" / "workspace" / "data" / "family-finances" DATA_DIR.mkdir(parents=True, exist_ok=True) BALANCE_FILE = DATA_DIR / "balance_sheet.json" CASHFLOW_FILE = DATA_DIR / "cashflow.json" PORTFOLIO_FILE = DATA_DIR / "portfolio.json" METADATA_FILE = DATA_DIR / "metadata.json"python def _save_json(path: Path, data): with open(path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)Technical Analysis
The Skill stores household assets, liabilities, income, expenses, investment holdings, descriptions, and notes as plaintext JSON. The data directory is created without an explicit restrictive mode, and files are opened without explicitly enforcing owner-only permissions.
Consequently, actual access permissions depend on the process umask and any permissions already present on the directory or files. In a permissively configured or multi-user environment, financial records may be readable by other local accounts. The implementation also does not correct weak permissions on existing files.
Exploitation requires local access under another account and filesystem permissions that permit traversal of the parent directories and reading of the generated files. This is not a remote vulnerability, and the code does not itself grant additional privileges.
Attack Path
- A user invokes an asset, liability, cash-flow, or portfolio command.
- The script creates or updates JSON files under
~/.openclaw/workspace/data/family-finances/. - Directory and file permissions are inherited from the host environment rather than explicitly restricted.
- If those effective permissions allow acces ...[truncated 822 chars]
- Remediation
View remediation
Remediation Suggestions
-
Create and enforce the data directory as owner-only:
python DATA_DIR.mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(DATA_DIR, 0o700) -
Create data files with mode
0o600usingos.open, so access does not rely solely on the process umask:python fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) -
Apply
os.chmod(path, 0o600)to existing financial files after verifying that the path is a regular file owned by the current user. -
Use atomic writes: write to an owner-only temporary file in the same restricted directory, flush and synchronize it, then replace the destination with
os.replace. -
Reject symbolic-link destinations before writing, or use platform-supported no-follow flags, to reduce the risk of unintended writes if the data directory is modified by another actor.
-
Consider encryption at rest when the threat model includes filesystem snapshots, backups, removable media, or privileged host users. Filesystem modes alone do not protect against administrators or other principals capable of bypassing discretionary access controls.
-
