T09 · Insecure Skill Coding Practices
- Location
scripts/src/core/storage.ts:58- Finding
Path Traversal and Arbitrary JSON File Access in Exported Storage Utilities
- Content
View full analysis
( data: T, category: string, operation: string, extraInfo?: string ): string { const settings = getSettings(); const categoryDir = join(settings.resultsDir, category); // Ensure category directory exists if (!existsSync(categoryDir)) { mkdirSync(categoryDir, { recursive: true }); } ``` ```typescript export function loadResult(filepath: string): SavedResult | null { if (!existsSync(filepath)) { return null; } try { const content = readFileSync(filepath, 'utf-8'); return JSON.parse(content) as SavedResult; } catch { return null; } } ``` ```typescript export function listResults(category: string, limit?: number): string[] { const settings = getSettings(); const categoryDir = join(settings.resultsDir, category); if (!existsSync(categoryDir)) { return []; } const files = readdirSync(categoryDir) .filter(f => f.endsWith('.json')) .map(f => join(categoryDir, f)) ``` The affected functions are made part of the public Skill interface: ```typescript export { saveResult, loadResult, listResults, getLatestResult } from './core/storage.js'; ``` ### Technical Analysis The `category` argument is joined directly to the configured results directory without an allowlist, canonicalization, or containment check. A value containing traversal components, such as `../../target`, can resolve outside the intended `results/` directory. Although generated filenames sanitize `operation` and `extraInfo`, this does not protect the directory component. Consequently, `saveResult` can create directories and write a generated JSON file in another filesystem location writable by the process. `listRe ...[truncated 1994 chars]- Remediation
View remediation
