T09 · Insecure Skill Coding Practices
- Location
scripts/lib/storage.py:6- Finding
Potentially Sensitive Case Data Stored Without Restrictive File Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/lib/storage.py:6-27andscripts/init_storage.py:6-16
Vulnerability Type: Plaintext sensitive-data storage with permissions dependent on the process umask
Risk Level: MediumVulnerable Code
scripts/lib/storage.py:6-27:python VERIFIER_DIR = os.path.expanduser("~/.openclaw/workspace/memory/verifier") CASES_FILE = os.path.join(VERIFIER_DIR, "cases.json") def ensure_dir(): os.makedirs(VERIFIER_DIR, exist_ok=True) def _safe_load(path, default): ensure_dir() if not os.path.exists(path): return default try: with open(path, "r", encoding="utf-8") as f: return json.load(f) except (json.JSONDecodeError, OSError): return default def _atomic_save(path, data): ensure_dir() tmp = path + ".tmp" with open(tmp, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) os.replace(tmp, path)scripts/init_storage.py:6-16:python VERIFIER_DIR = os.path.expanduser("~/.openclaw/workspace/memory/verifier") CASES_FILE = os.path.join(VERIFIER_DIR, "cases.json") def write_json_if_missing(path, payload): if not os.path.exists(path): with open(path, "w", encoding="utf-8") as f: json.dump(payload, f, indent=2, ensure_ascii=False) def main(): os.makedirs(VERIFIER_DIR, exist_ok=True) write_json_if_missing(CASES_FILE, {Technical Analysis
The Skill stores arbitrary claims, suspicious messages, profile information, offers, notes, source labels, and evidence in a plaintext JSON file under the user's home directory. This information may contain personal, confidential, or security-sensitive data.
The storage directory, final JSON file, and predictable temporary file are created without explicit owner-only permissions. Their permissions consequently depend on the process umask. Under a common
022umask, newly created directories are typically mode0755and files m ...[truncated 1776 chars]- Remediation
View remediation
Remediation Suggestions
- Create the storage directory with owner-only permissions and repair permissions if it already exists:
python def ensure_dir(): os.makedirs(VERIFIER_DIR, mode=0o700, exist_ok=True) os.chmod(VERIFIER_DIR, 0o700)- Securely create the temporary file with mode
0600rather than relying on the process umask:
python def _atomic_save(path, data): ensure_dir() tmp = path + ".tmp" fd = os.open(tmp, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) try: with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) f.flush() os.fsync(f.fileno()) os.replace(tmp, path) os.chmod(path, 0o600) except Exception: try: os.unlink(tmp) except OSError: pass raise-
Prefer
tempfile.NamedTemporaryFilein the same directory with restrictive permissions and a non-predictable name, followed byos.replace(). -
During initialization, inspect and correct permissions on an existing storage directory and
cases.json. -
Document that case records are stored in plaintext and advise users not to include credentials, authentication tokens, private keys, or unnecessary personal data.
-
If the deployment threat model includes hostile local users or compromised backups, provide authenticated encryption at rest with keys stored separately from the case database.
