T09 · Insecure Skill Coding Practices
- Location
index.js:155- Finding
Unrestricted Local File Read and Derived-Path Write
- Content
View full analysis
\nOptimizes existing content for SEO and readability.'; } if (!fs.existsSync(filepath)) { return `File not found: ${filepath}`; } const content = fs.readFileSync(filepath, 'utf8'); const config = loadConfig(); const optimized = await optimizeContent(content, config); const newPath = filepath.replace(/\.(\w+)$/, '-optimized.$1'); fs.writeFileSync(newPath, optimized); return `✅ Content optimized!\n📁 Saved to: ${newPath}\n\nKey improvements:\n- SEO score increased\n- Readability enhanced\n- Tone adjusted to ${config.tone}`; } ``` The same unrestricted path behavior is present in the analysis and export handlers: ```js const filepath = args[0]; if (!fs.existsSync(filepath)) { return `File not found: ${filepath}`; } const content = fs.readFileSync(filepath, 'utf8'); ``` ```js const filepath = args[1]; if (!fs.existsSync(filepath)) { return `File not found: ${filepath}`; } const content = fs.readFileSync(filepath, 'utf8'); const exported = await exportContent(content, format); const ext = format === 'html' ? 'html' : format === 'pdf' ? 'pdf' : format === 'docx' ? 'docx' : 'md'; const newPath = filepath.replace(/\.\w+$/, `.${ext}`); fs.writeFileSync(newPath, exported); ``` ### Technical Analysis The `optimize`, `analyze`, and `export` commands accept a caller-controlled path and pass it directly to `fs.existsSync`, `fs.readFileSync`, and, in some cases, `fs.writeFileSync`. The path is not canonicalized, restricted to the Skill's content directory, checked for symbolic links, or validated against an allowli ...[truncated 1899 chars]- Remediation
View remediation
