T09 · Insecure Skill Coding Practices
- Location
src/index.js:16- Finding
Path Traversal Allows File Operations Outside the Intended Data Directory
- Content
View full analysis
').description('Delete a specified task list').action(name => { const dataFile = path.join(BASE_DIR, `${name}_tasktodolist.json`); if (fs.existsSync(dataFile)) { fs.unlinkSync(dataFile); console.log(`Deleted task list: [${name}]`); } else { console.error(`Task list not found: [${name}]`); } }); ``` The English wording in the second snippet reflects the behavior of the original localized messages; the executable path construction and file operations are unchanged. ### Technical Analysis The application intends to confine all persistent data to `~/.tasktodolist`. However, both `getTaskName()` and the `tasks rm ` handler accept arbitrary user-controlled strings. These values are passed to `path.join()` without rejecting path separators, `..` traversal components, or symbolic-link targets. When a name contains enough parent-directory components, normalization ca ...[truncated 3105 chars]- Remediation
View remediation
` argument. 2. **Resolve the final path and enforce directory confinement** Validation should be supplemented with a containment check: ```js function getDataFileForName(rawName) { const name = validateTaskName(rawName); const base = path.resolve(BASE_DIR); const candidate = path.resolve(base, `${name}_tasktodolist.json`); if (!candidate.startsWith(`${base}${path.sep}`)) { throw new Error('Task path escapes the data directory'); } return candidate; } ``` Use this single function for all reads, writes, and deletions so that security checks cannot diverge between commands. 3. **Reject symbolic-link targets** Before reading, writing, or deleting an existing data file, use `fs.lstatSync()` and reject symbolic links: ```js if (fs.existsSync(candidate) && fs.lstatSync(candidate).isSymbolicLink()) { throw new Error('Symbolic-link task files are not allowed'); } ``` Where supported, use file-opening flags and APIs that prevent following symbolic links and reduce time-of-check/time-of-use race conditions. 4. **Harden file creation** Create the base directory with restrictive permissions and create new data files with an explicit mode suitable for private user data: ```js fs.mkdirSync(BASE_DIR, { recursive: true, mode: 0o700 }); fs.writeFileSync(candidate, '[]', { encoding: 'utf8', mode: 0o600, flag: 'wx' }); ``` Handle the case where the file already exists rather than replacing it during initialization. 5. **Handle invalid JSON ex ...[truncated 182 chars]
