T09 · Insecure Skill Coding Practices
- Location
bin/reg-limited.js:232- Finding
Reminder Data Stored in Plaintext Without Restrictive File Permissions
- Content
View full analysis
Vulnerability Details
File Location:
bin/reg-limited.js:232-256
Vulnerability Type: Insecure local storage of personal data
Risk Level: MediumVulnerable Code
js const fs = require('fs'); const configPath = process.env.HOME + '/.reg-limited/config.json'; let config = { reminders: [] }; try { if (fs.existsSync(configPath)) { config = JSON.parse(fs.readFileSync(configPath)); } } catch (e) {} const reminder = { id: Date.now().toString(), city, plate, time, created: new Date().toISOString() }; config.reminders.push(reminder); const dir = require('path').dirname(configPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(configPath, JSON.stringify(config, null, 2));Technical Analysis
The application stores vehicle plate numbers, cities, reminder times, and creation timestamps in the predictable path
~/.reg-limited/config.json. The data is serialized directly as plaintext JSON.Neither
fs.mkdirSync()norfs.writeFileSync()specifies a restrictive permission mode. Consequently, permissions are determined by the process umask. Under a commonly used umask such as0022, the directory can be created with mode0755and the file with mode0644, potentially making the reminder data readable by other local users.The implementation also does not verify the ownership or existing type of the configuration directory and file before accessing them. The confirmed exposure is the absence of explicit access controls for the stored personal data.
Attack Path
- A user invokes
reg-limited addwith a city, vehicle plate, and reminder time. - The application places those values into the
reminderobject. - The directory and configuration file are created using permissions derived from the environment's umask.
- On a shared system with permissive resulting permissions, another local ...[truncated 911 chars]
- A user invokes
- Remediation
View remediation
Remediation Suggestions
-
Create the configuration directory with owner-only permissions:
js fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); -
Create and write the configuration file with mode
0600:js fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: 'utf8', mode: 0o600 }); -
Apply restrictive permissions to existing installations using
fs.chmodSync(dir, 0o700)andfs.chmodSync(configPath, 0o600)where appropriate. -
Before reading or replacing an existing file, use
lstatand ownership checks to ensure it is a regular file owned by the current user rather than an unexpected filesystem object. -
Write updates to an owner-only temporary file in the same protected directory and atomically rename it to the destination to reduce corruption and replacement risks.
-
Minimize retained personal data. If the complete plate is unnecessary for reminders, store a masked or otherwise reduced representation. If full plate retention is required, consider encryption backed by an operating-system credential store.
-
