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

Function extractHeredocs

src/utils/bash/heredoc.ts:113–687  ·  view source on GitHub ↗
(
  command: string,
  options?: { quotedOnly?: boolean },
)

Source from the content-addressed store, hash-verified

111 * ```
112 */
113export function extractHeredocs(
114 command: string,
115 options?: { quotedOnly?: boolean },
116): HeredocExtractionResult {
117 const heredocs = new Map<string, HeredocInfo>()
118
119 // Quick check: if no << present, skip processing
120 if (!command.includes('<<')) {
121 return { processedCommand: command, heredocs }
122 }
123
124 // Security: Paranoid pre-validation. Our incremental quote/comment scanner
125 // (see advanceScan below) does simplified parsing that cannot handle all
126 // bash quoting constructs. If the command contains
127 // constructs that could desync our quote tracking, bail out entirely
128 // rather than risk extracting a heredoc with incorrect boundaries.
129 // This is defense-in-depth: each construct below has caused or could
130 // cause a security bypass if we attempt extraction.
131 //
132 // Specifically, we bail if the command contains:
133 // 1. $'...' or $"..." (ANSI-C / locale quoting — our quote tracker
134 // doesn't handle the $ prefix, would misparse the quotes)
135 // 2. Backtick command substitution (backtick nesting has complex parsing
136 // rules, and backtick acts as shell_eof_token for PST_EOFTOKEN in
137 // make_cmd.c:606, enabling early heredoc closure that our parser
138 // can't replicate)
139 if (/\$['"]/.test(command)) {
140 return { processedCommand: command, heredocs }
141 }
142 // Check for backticks in the command text before the first <<.
143 // Backtick nesting has complex parsing rules, and backtick acts as
144 // shell_eof_token for PST_EOFTOKEN (make_cmd.c:606), enabling early
145 // heredoc closure that our parser can't replicate. We only check
146 // before << because backticks in heredoc body content are harmless.
147 const firstHeredocPos = command.indexOf('<<')
148 if (firstHeredocPos > 0 && command.slice(0, firstHeredocPos).includes('`')) {
149 return { processedCommand: command, heredocs }
150 }
151
152 // Security: Check for arithmetic evaluation context before the first `<<`.
153 // In bash, `(( x = 1 << 2 ))` uses `<<` as a BIT-SHIFT operator, not a
154 // heredoc. If we mis-extract it, subsequent lines become "heredoc content"
155 // and are hidden from security validators, while bash executes them as
156 // separate commands. We bail entirely if `((` appears before `<<` without
157 // a matching `))` — we can't reliably distinguish arithmetic `<<` from
158 // heredoc `<<` in that context. Note: $(( is already caught by
159 // validateDangerousPatterns, but bare (( is not.
160 if (firstHeredocPos > 0) {
161 const beforeHeredoc = command.slice(0, firstHeredocPos)
162 // Count (( and )) occurrences — if unbalanced, `<<` may be arithmetic
163 const openArith = (beforeHeredoc.match(/\(\(/g) || []).length
164 const closeArith = (beforeHeredoc.match(/\)\)/g) || []).length
165 if (openArith > closeArith) {
166 return { processedCommand: command, heredocs }
167 }
168 }
169
170 // Create a global version of the pattern for iteration

Calls 5

advanceScanFunction · 0.85
generatePlaceholderSaltFunction · 0.85
forEachMethod · 0.80
pushMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected