T09 · Insecure Skill Coding Practices
- Location
scripts/send-card.js:119- Finding
Template path validation can be bypassed through prefix collisions and symbolic links
- Content
View full analysis
resolvedPath.startsWith(dir)); if (!isAllowed) { console.error('Security error: template file must be in an allowed directory'); allowedDirs.forEach(dir => console.error(` - ${dir}`)); console.error(`\nAttempted path: ${resolvedPath}`); process.exit(1); } // 4. Check the file extension const ext = path.extname(resolvedPath).toLowerCase(); if (ext !== '.json') { console.error('Security error: template file must use the .json extension'); process.exit(1); } // 5. Check whether the file exists if (!fs.existsSync(resolvedPath)) { console.error('File does not exist:', resolvedPath); process.exit(1); } // 6. Read and validate JSON try { const content = fs.readFileSync(resolvedPath, 'utf8'); card = JSON.parse(content); ``` ### Technical Analysis The validation uses a raw string-prefix comparison: ```javascript resolvedPath.startsWith(dir) ``` A string prefix does not establish that the candidate is a descendant of the allowed directory. For example, if `/app/examples` is allowed, a file such as `/app/examples-private/card.json` also starts with `/app/examples` and passes the check. The validation also operates on the lexical path returned by `path.resolve()` rather than the canonical filesystem path. A symbolic link located inside an allowed directory can therefore point to a JSON file outside t ...[truncated 1700 chars]- Remediation
View remediation
