T09 · Insecure Skill Coding Practices
- Location
scripts/idea_inbox_config.py:66- Finding
Sensitive Configuration File Is Written Without Restrictive Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/idea_inbox_config.py, lines 66-68
Vulnerability Type: CWE-732 — Incorrect Permission Assignment for Critical Resource
Risk Level: MediumVulnerable Code
python def save_config(cfg: dict[str, Any]) -> None: CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True) CONFIG_PATH.write_text(json.dumps(cfg, ensure_ascii=False, indent=2), encoding="utf-8")Technical Analysis
The configuration is written using
Path.write_text()without explicitly setting owner-only permissions on either the configuration directory or file. Consequently, the resulting permissions depend on the process umask.The documented configuration can contain a Bitable application token and an optional fallback model API key. If the process runs with a permissive umask, another local account may be able to read
~/.openclaw/idea-inbox/config.json. Existing files with insecure permissions also remain insecure when overwritten because the implementation does not correct their mode.Attack Path
- A user configures the Skill with a Bitable token or fallback model API key.
save_config()creates or updates the configuration without enforcing restrictive permissions.- The host has a permissive umask, or the configuration file already has group- or world-readable permissions.
- Another local user reads
~/.openclaw/idea-inbox/config.json. - The attacker reuses any exposed API credentials or resource identifiers according to the permissions granted by the corresponding external service.
This attack requires local filesystem access under an account that can read the resulting file. Its feasibility therefore depends on the host's umask, existing file permissions, and account isolation.
Impact Assessment
A successful attacker could consume model API quota or invoke model APIs with the exposed key. If the stored Bitable values provide or can be combined with ...[truncated 270 chars]
- Remediation
View remediation
Remediation Suggestions
- Create the configuration directory with owner-only permissions (
0700). - Create configuration files with mode
0600, independent of the process umask. - Write updates to an owner-only temporary file in the same directory, flush and synchronize it, then atomically replace the destination.
- Explicitly apply
chmod(0o600)after replacement so pre-existing files with unsafe permissions are corrected. - Store API keys in an operating-system credential store or another protected secret manager instead of plaintext JSON where possible.
- Validate that the configured path is not a symbolic link before writing if untrusted local users can modify the parent path.
Example hardening approach:
python def save_config(cfg: dict[str, Any]) -> None: CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True, mode=0o700) CONFIG_PATH.parent.chmod(0o700) data = json.dumps(cfg, ensure_ascii=False, indent=2) temp_path = CONFIG_PATH.with_suffix(".tmp") fd = os.open(temp_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) try: with os.fdopen(fd, "w", encoding="utf-8") as handle: handle.write(data) handle.flush() os.fsync(handle.fileno()) os.replace(temp_path, CONFIG_PATH) CONFIG_PATH.chmod(0o600) finally: if temp_path.exists(): temp_path.unlink()- Create the configuration directory with owner-only permissions (
