- Location
- scripts/utils.js:20
- Finding
- Sensitive Personal Data Stored Without Restrictive File Permissions<![CDATA[
## Vulnerability Details
**File Location**: `scripts/utils.js:20-56`
**Vulnerability Type**: Plaintext sensitive-data storage with insufficient access controls
**Risk Level**: Medium
### Vulnerable Code
```javascript
function ensureDataDir() {
const d = getDataDir();
if (!fs.existsSync(d)) {
fs.mkdirSync(d, { recursive: true });
}
return d;
}
/** 初始化默认数据目录与空数据文件 */
function initDataDir() {
const d = ensureDataDir();
const defaults = {
portraits: { people: {} },
past_events: { events: [] },
future_events: { events: [] },
reminders_sent: { sent: {} },
};
for (const [name, data] of Object.entries(defaults)) {
const filePath = path.join(d, `${name}.json`);
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
}
}
return d;
}
function loadJson(name) {
const filePath = path.join(getDataDir(), `${name}.json`);
if (!fs.existsSync(filePath)) return {};
const raw = fs.readFileSync(filePath, 'utf-8');
try {
return JSON.parse(raw);
} catch {
return {};
}
}
function saveJson(name, data) {
ensureDataDir();
const filePath = path.join(getDataDir(), `${name}.json`);
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
}
```
### Technical Analysis
The Skill is explicitly designed to store sensitive personal information, including phone numbers, residential addresses, birth dates, personal notes, social relationships, and historical or future events. These records are written as unencrypted JSON.
The directory is created without an explicit mode such as `0700`, and files are written without an explicit mode such as `0600`. Consequently, access permissions depend on the process umask. On systems with a common umask of `022`, newly created files may be readable by other local users.
The default storage location is the package's `data/` directory. Keeping personal records inside the Skill installation directory also incr
...[truncated 1320 chars]
- Remediation
- <![CDATA[
## Remediation Suggestions
1. Store data in a private user-data directory rather than inside the installed Skill directory.
2. Create the data directory with owner-only permissions:
```javascript
fs.mkdirSync(d, { recursive: true, mode: 0o700 });
fs.chmodSync(d, 0o700);
```
3. Create and maintain data files with owner-only permissions:
```javascript
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), {
encoding: 'utf8',
mode: 0o600,
});
fs.chmodSync(filePath, 0o600);
```
4. Use atomic writes through a private temporary file followed by `renameSync()` to reduce corruption and permission inconsistencies.
5. Warn users that these files contain sensitive personal data and should not be committed, shared, or synchronized without appropriate protection.
6. Add the data files to `.gitignore` and distribute only empty templates.
7. Consider optional encryption at rest when the threat model includes other local users, shared backups, or synchronized storage.
]]>