T09 · Insecure Skill Coding Practices
- Location
', 'Read content from file') .option('--stdin', 'Read content from stdin') .option('--overwrite', 'Overwrite if exists') .option('--no-index', 'Skip qmd index update (auto-updates by default)') .option('--embed', 'Also update qmd embeddings for vector search') .option('-v, --vault <path>', 'Vault path (default: find nearest)') .action(async (options) => { try { const vault = await getVault(options.vault); let content = options.content || ''; if (options.file) { co ...[truncated 2397 chars]:195- Finding
Path Traversal Allows Markdown Writes Outside the Vault
- Content
View full analysis
{ const { category, title, content, frontmatter = {}, overwrite = false, qmdUpdate: triggerUpdate = false, qmdEmbed: triggerEmbed = false } = options; // Create filename from title const filename = this.slugify(title) + '.md'; const relativePath = path.join(category, filename); const fullPath = path.join(this.config.path, relativePath); // Check if exists if (fs.existsSync(fullPath) && !overwrite) { throw new Error(`Document already exists: ${relativePath}. Use overwrite: true to replace.`); } // Ensure category directory exists const categoryPath = path.join(this.config.path, category); if (!fs.existsSync(categoryPath)) { fs.mkdirSync(categoryPath, { recursive: true }); } // Build frontmatter with date const fm = { title, date: new Date().toISOString().split('T')[0], ...frontmatter }; // Write file const fileContent = matter.stringify(content, fm); fs.writeFileSync(fullPath, fileContent); ``` The corresponding CLI option accepts an unrestricted category: ```js program .command('store') .description('Store a new memory') .requiredOption( '-c, --category ', 'Category (preferences, decisions, patterns, people, projects, goals, transcripts, inbox)' ) .requiredOption('-t, --title ', 'Document title') .option('--content <content>', 'Content body') .option('-f, --file <file>', 'Read content from file') .option('--stdin', 'Read content from stdin') .option('--overwrite', 'Overwrite if exists') .option('--no-index', 'Skip qmd index update (auto-updates by default)') .option('--embed', 'Also update qmd embeddings for vector search') .opt ...[truncated 2518 chars]- Remediation
View remediation
