diff --git a/src/utils/cli-helpers.ts b/src/utils/cli-helpers.ts index f68dcbe..d0f2de1 100644 --- a/src/utils/cli-helpers.ts +++ b/src/utils/cli-helpers.ts @@ -14,9 +14,12 @@ export function formatParam(key: string, value: string | number): string { // Always quote string values to handle spaces and special characters safely // Note: Obsidian CLI docs say: "Quote values with spaces: name="My Note"" - // Escape any double quotes in the value to prevent shell interpretation issues - // This prevents truncation when content contains quotes like "Bot QM" - const escapedValue = String(value).replace(/"/g, '\\"'); + // Escape double quotes and backticks to prevent shell interpretation inside double-quoted strings. + // In bash double-quoted strings: \" prevents quote termination, \` prevents command substitution. + // This preserves Markdown code fences (``` ` ```) while blocking injection via backticks. + const escapedValue = String(value) + .replace(/"/g, '\\"') + .replace(/`/g, '\\`'); return `${key}="${escapedValue}"`; } diff --git a/src/validation/sanitizer.ts b/src/validation/sanitizer.ts index d7bff0c..3c38636 100644 --- a/src/validation/sanitizer.ts +++ b/src/validation/sanitizer.ts @@ -11,13 +11,14 @@ import { logger } from '../utils/logger.js'; * Note: Brackets [], parentheses (), and braces {} are safe because values are quoted and passed as array args * They're essential for Obsidian markdown (wikilinks [[link]], tasks - [ ] Task, templates {{...}}, etc.) * Note: Single & is safe in quoted args (filenames like "Research & Development.md") - * We only block: ; | ` $ < > (command separators, pipes, substitution, redirects) + * Note: Backticks are safe because formatParam escapes them as \` inside double-quoted strings, + * preventing shell command substitution while preserving Markdown code fences (``` ```) + * We only block: ; | $ < > (command separators, pipes, substitution, redirects) * Command injection patterns (&&, ||, etc.) are handled separately */ -const DANGEROUS_CHARS = /[;|`$<>]/g; +const DANGEROUS_CHARS = /[;|$<>]/g; const COMMAND_INJECTION_PATTERNS = [ /\$\(/g, // Command substitution $(...) - /`[^`]*`/g, // Command substitution `...` /\|\|/g, // OR operator /&&/g, // AND operator /;/g, // Command separator