T09 · Insecure Skill Coding Practices
- Location
scripts/update-task-stats.js:62- Finding
Incorrect delimiter validation can corrupt the target task file
- Content
View full analysis
Vulnerability Details
File Location:
scripts/update-task-stats.js, lines 62–68
Vulnerability Type: Improper validation of a section delimiter before an in-place file write
Risk Level: MediumVulnerable Code
js const statsStart = content.indexOf('## 任务统计'); const statsEnd = content.indexOf('---', statsStart) + 3; if (statsStart === -1 || statsEnd === -1) { console.error('Could not find stats section in file'); process.exit(1); } const newContent = content.substring(0, statsStart) + newStats + content.substring(statsEnd);The resulting content is subsequently written directly over the source file:
js try { fs.writeFileSync(filePath, newContent, 'utf8'); console.log('Task statistics updated successfully'); console.log(`Total: ${totalTasks}, Running: ${running}, Completed: ${completed}`); console.log(`Persistent: ${persistent}, One-time: ${oneTime}`); } catch (err) { console.error(`Error writing file: ${err.message}`); process.exit(1); }Technical Analysis
String.prototype.indexOf()returns-1when the requested delimiter is absent. The script adds3to that result before validating it:js const statsEnd = content.indexOf('---', statsStart) + 3;If the delimiter is missing,
statsEndbecomes2, not-1. Therefore, the conditionstatsEnd === -1cannot detect this failure. A file containing the expected statistics heading but no subsequent---delimiter passes validation.The script then constructs replacement content using offset
2as the end of the old statistics section. Because it writes the result directly over the original file without a backup, temporary file, or atomic rename, malformed input can cause destructive rearrangement or duplication of file content.The caller controls the target path through
process.argv[2]. Exploitation therefore requires the ability to supply or influence both the processed path and its content, or to modify the normal task file before the ...[truncated 1438 chars]- Remediation
View remediation
Remediation Suggestions
Validate the raw delimiter-search result before performing arithmetic:
js const statsStart = content.indexOf('## 任务统计'); const delimiterStart = statsStart === -1 ? -1 : content.indexOf('---', statsStart); if (statsStart === -1 || delimiterStart === -1) { console.error('Could not find a valid stats section in file'); process.exit(1); } const statsEnd = delimiterStart + '---'.length; const newContent = content.substring(0, statsStart) + newStats + content.substring(statsEnd);Apply the following additional hardening measures:
- Verify that the heading and delimiter occur in the expected order and represent a complete statistics section.
- Parse the Markdown structure more strictly instead of relying on unrestricted substring searches.
- Write the updated content to a temporary file in the same directory and atomically rename it over the original only after all validation and writes succeed.
- Preserve a backup when processing user-important task records.
- Restrict accepted targets where appropriate, such as requiring a
.mdfile within an approved workspace. - Add tests for a missing heading, missing delimiter, delimiter before the heading, empty content, truncated content, multiple statistics sections, and write failures.
