From 6e5b45ed28832abdd32968721115bc3e9a260c5f Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Thu, 12 Feb 2026 14:14:21 -0800 Subject: [PATCH] fix: path traversal in install.sh, error logging in hooks - Validate language names in install.sh to prevent path traversal via malicious args like ../../etc (only allow [a-zA-Z0-9_-]) - Replace silent catch in check-console-log.js with stderr logging so hook failures are visible to the user for debugging - Escape backticks in session-end.js user messages to prevent markdown structure corruption in session files --- install.sh | 10 ++++++++++ scripts/hooks/check-console-log.js | 4 ++-- scripts/hooks/session-end.js | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/install.sh b/install.sh index 9aff2bd4..f7d9c89b 100755 --- a/install.sh +++ b/install.sh @@ -69,6 +69,11 @@ if [[ "$TARGET" == "claude" ]]; then # Install each requested language for lang in "$@"; do + # Validate language name to prevent path traversal + if [[ ! "$lang" =~ ^[a-zA-Z0-9_-]+$ ]]; then + echo "Error: invalid language name '$lang'. Only alphanumeric, dash, and underscore allowed." >&2 + continue + fi lang_dir="$RULES_DIR/$lang" if [[ ! -d "$lang_dir" ]]; then echo "Warning: rules/$lang/ does not exist, skipping." >&2 @@ -101,6 +106,11 @@ if [[ "$TARGET" == "cursor" ]]; then # Install language-specific rules for lang in "$@"; do + # Validate language name to prevent path traversal + if [[ ! "$lang" =~ ^[a-zA-Z0-9_-]+$ ]]; then + echo "Error: invalid language name '$lang'. Only alphanumeric, dash, and underscore allowed." >&2 + continue + fi if [[ -d "$CURSOR_SRC/rules" ]]; then found=false for f in "$CURSOR_SRC/rules"/${lang}-*.md; do diff --git a/scripts/hooks/check-console-log.js b/scripts/hooks/check-console-log.js index be290534..2cf0b09f 100755 --- a/scripts/hooks/check-console-log.js +++ b/scripts/hooks/check-console-log.js @@ -59,8 +59,8 @@ process.stdin.on('end', () => { if (hasConsole) { log('[Hook] Remove console.log statements before committing'); } - } catch { - // Silently ignore errors (git might not be available, etc.) + } catch (err) { + log(`[Hook] check-console-log error: ${err.message}`); } // Always output the original data diff --git a/scripts/hooks/session-end.js b/scripts/hooks/session-end.js index de7c8afd..cc4abd1a 100644 --- a/scripts/hooks/session-end.js +++ b/scripts/hooks/session-end.js @@ -157,10 +157,10 @@ ${summarySection} function buildSummarySection(summary) { let section = '## Session Summary\n\n'; - // Tasks (from user messages) + // Tasks (from user messages — escape backticks to prevent markdown breaks) section += '### Tasks\n'; for (const msg of summary.userMessages) { - section += `- ${msg}\n`; + section += `- ${msg.replace(/`/g, '\\`')}\n`; } section += '\n';