MCPcopy Index your code
hub / github.com/codeaashu/claude-code / stripAllLeadingEnvVars

Function stripAllLeadingEnvVars

src/tools/BashTool/bashPermissions.ts:733–776  ·  view source on GitHub ↗
(
  command: string,
  blocklist?: RegExp,
)

Source from the content-addressed store, hash-verified

731 * BINARY_HIJACK_VARS for excludedCommands.
732 */
733export function stripAllLeadingEnvVars(
734 command: string,
735 blocklist?: RegExp,
736): string {
737 // Broader value pattern for deny-rule stripping. Handles:
738 //
739 // - Standard assignment (FOO=bar), append (FOO+=bar), array (FOO[0]=bar)
740 // - Single-quoted values: '[^'\n\r]*' — bash suppresses all expansion
741 // - Double-quoted values with backslash escapes: "(?:\\.|[^"$`\\\n\r])*"
742 // In bash double quotes, only \$, \`, \", \\, and \newline are special.
743 // Other \x sequences are harmless, so we allow \. inside double quotes.
744 // We still exclude raw $ and ` (without backslash) to block expansion.
745 // - Unquoted values: excludes shell metacharacters, allows backslash escapes
746 // - Concatenated segments: FOO='x'y"z" — bash concatenates adjacent segments
747 //
748 // SECURITY: Trailing whitespace MUST be [ \t]+ (horizontal only), NOT \s+.
749 //
750 // The outer * matches one atomic unit per iteration: a complete quoted
751 // string, a backslash-escape pair, or a single unquoted safe character.
752 // The inner double-quote alternation (?:...|...)* is bounded by the
753 // closing ", so it cannot interact with the outer * for backtracking.
754 //
755 // Note: $ is excluded from unquoted/double-quoted value classes to block
756 // dangerous forms like $(cmd), ${var}, and $((expr)). This means
757 // FOO=$VAR is not stripped — adding $VAR matching creates ReDoS risk
758 // (CodeQL #671) and $VAR bypasses are low-priority.
759 const ENV_VAR_PATTERN =
760 /^([A-Za-z_][A-Za-z0-9_]*(?:\[[^\]]*\])?)\+?=(?:'[^'\n\r]*'|"(?:\\.|[^"$`\\\n\r])*"|\\.|[^ \t\n\r$`;|&()<>\\\\'"])*[ \t]+/
761
762 let stripped = command
763 let previousStripped = ''
764
765 while (stripped !== previousStripped) {
766 previousStripped = stripped
767 stripped = stripCommentLines(stripped)
768
769 const m = stripped.match(ENV_VAR_PATTERN)
770 if (!m) continue
771 if (blocklist?.test(m[1]!)) break
772 stripped = stripped.slice(m[0].length)
773 }
774
775 return stripped.trim()
776}
777
778function filterRulesByContentsMatchingInput(
779 input: z.infer<typeof BashTool.inputSchema>,

Callers 2

containsExcludedCommandFunction · 0.85

Calls 1

stripCommentLinesFunction · 0.85

Tested by

no test coverage detected