T09 · Insecure Skill Coding Practices
- Location
scripts/cli.js:15- Finding
Plaintext Sensitive Case Records Stored Without Explicitly Restrictive Permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/cli.js, lines 15–25 and 44–53
Vulnerability Type: Plaintext sensitive-data storage with unsafe reliance on inherited filesystem permissions
Risk Level: MediumVulnerable Code
js const DATA_DIR = path.join(process.env.HOME || process.env.USERPROFILE, '.openclaw', 'skills-data', 'looking-for-someone'); const CASES_FILE = path.join(DATA_DIR, 'cases.json'); // Ensure data directory exists if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, { recursive: true }); } // Initialize cases file if it doesn't exist if (!fs.existsSync(CASES_FILE)) { fs.writeFileSync(CASES_FILE, JSON.stringify([], null, 2)); } // Save cases function saveCases(cases) { try { fs.writeFileSync(CASES_FILE, JSON.stringify(cases, null, 2)); return true; } catch (error) { console.error('Error saving cases:', error.message); return false; } }Technical Analysis
The application handles sensitive missing-person information, including names, dates of birth, phone numbers, identification numbers, family contacts, locations, distinguishing features, circumstances, and investigative clues. All case records are serialized directly into a single unencrypted JSON file.
The data directory and file are created without explicit modes. Consequently, their effective permissions depend on the process umask and the permissions of parent directories. A permissive or misconfigured environment may create a file that other local users can read. The implementation neither verifies ownership and permissions of an existing file nor rejects symbolic links at the expected data path.
Although the documentation acknowledges that encryption is not implemented, disclosure does not mitigate the confidentiality risk. The particularly sensitive nature of missing-person records warrants restrictive permissions independent of the ambient umask.
Attack Path
- A user invokes the
createorcluecommand and suppl ...[truncated 1280 chars]
- A user invokes the
- Remediation
View remediation
Remediation Suggestions
- Create the private data directory with owner-only permissions:
js fs.mkdirSync(DATA_DIR, { recursive: true, mode: 0o700 }); fs.chmodSync(DATA_DIR, 0o700);- Create and maintain the case file with mode
0600:
js fs.writeFileSync(CASES_FILE, JSON.stringify([], null, 2), { encoding: 'utf8', mode: 0o600, flag: 'wx' });For later writes, verify ownership and file type first, write to an owner-only temporary file in the same directory, flush it, and atomically rename it over the destination. Reapply mode
0600after replacement.-
Use
lstatand platform-appropriate secure-open flags to reject symbolic links and non-regular files. Verify that the directory and existing case file are owned by the current user before reading or writing. -
Add schema-based data minimization. Do not persist unknown fields, and warn users before storing high-risk fields such as identification numbers, exact addresses, medical details, or financial information.
-
Consider authenticated encryption for especially sensitive fields or the complete case database. Keep encryption keys outside the data file and use an operating-system credential store where available.
-
Add automated tests that run under permissive umask settings and verify that the directory remains
0700and the case file remains0600. -
Provide implemented deletion, retention, and export controls so sensitive records can be removed when no longer required.
