#6257: Fix: Create sensitive directories with mode 0o700
Cluster:
Config File Security Enhancements
## Summary
Fixes #6251 - Sensitive directories under `~/.openclaw/` were created with mode 755 (world-readable) instead of 700 (owner-only).
## Root Cause
The `ensureDir()` function in `src/infra/device-identity.ts` created the identity directory without specifying a mode:
```typescript
function ensureDir(filePath: string) {
fs.mkdirSync(path.dirname(filePath), { recursive: true }); // No mode!
}
```
This inherits the default umask (typically 022), resulting in 755 permissions.
## The Fix
### 1. `src/infra/device-identity.ts`
- Renamed `ensureDir` to `ensureSecureDir` with explicit `mode: 0o700`
- Added `chmod` call to fix existing directories that may have wrong permissions
- The identity directory contains **private keys** and must not be world-readable
### 2. `src/utils.ts`
- Added optional `mode` parameter to `ensureDir()`
- When mode is specified, also applies `chmod` to fix existing directories
## Defense in Depth
Even though the parent `~/.openclaw` directory is correctly set to 700, subdirectories should also be locked down because:
- If parent permissions are ever loosened (e.g., for shared workspace access), sensitive directories would be exposed
- Principle of least privilege
## Before/After
```
# Before
drwx------ ~/.openclaw/ (700) ✓
drwxr-xr-x ~/.openclaw/identity/ (755) ← WRONG
# After
drwx------ ~/.openclaw/ (700) ✓
drwx------ ~/.openclaw/identity/ (700) ✓
```
---
*First OpenClaw contribution! Found this while setting up my own agent identity.* 🦝
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR tightens filesystem permissions for state directories, particularly the device identity directory under `~/.openclaw/`, by creating it with `0o700` and best-effort `chmod`ing existing directories to match. It also extends the shared `ensureDir()` helper to optionally accept a mode and apply `chmod` when provided, so other state directories can be made secure consistently across the codebase.
<h3>Confidence Score: 3/5</h3>
- Mergeable after fixing a runtime-compatibility issue in `ensureDir()` around passing `mode: undefined`.
- The security intent is sound and localized, but the new optional parameter implementation may break directory creation at runtime in environments where Node rejects `mode: undefined`, affecting multiple call sites.
- src/utils.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#17463: fix: write config files with explicit 0o600 mode instead of post-wr...
by miclaldogan · 2026-02-15
80.3%
#18954: fix(security): secure cron, browser, settings dirs in doctor --fix
by BinHPdev · 2026-02-17
78.1%
#7007: Fix security audit false-positive for symlinked state dir
by MohammadErfan-Jabbari · 2026-02-02
78.1%
#23432: Doctor: prevent permissive secret file modes during --fix
by bmendonca3 · 2026-02-22
77.9%
#17916: [ fix ] : correct config directory path during onboarding
by Dijo-404 · 2026-02-16
76.9%
#19032: fix(security): tighten permissions for cron/, browser/, settings/ i...
by moxunjinmu · 2026-02-17
76.8%
#18924: fix(security): tighten permissions on cron/, browser/, settings/ dirs…
by rexlunae · 2026-02-17
76.6%
#19191: fix(security): harden cron file permissions to 0o600
by Kropiunig · 2026-02-17
76.4%
#18939: fix: tighten permissions on cron/, browser/, settings/, logs/ in do...
by sriram369 · 2026-02-17
76.2%
#18959: fix: harden permissions on cron/, browser/, settings/ in doctor --fix
by jwchmodx · 2026-02-17
76.1%