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

Function walkCommand

src/utils/bash/ast.ts:1237–1363  ·  view source on GitHub ↗

* Walk a `command` node and extract argv. Children appear in order: * [variable_assignment...] command_name [argument...] [file_redirect...] * Any child type not explicitly handled triggers too-complex.

(
  node: Node,
  extraRedirects: Redirect[],
  innerCommands: SimpleCommand[],
  varScope: Map<string, string>,
)

Source from the content-addressed store, hash-verified

1235 * Any child type not explicitly handled triggers too-complex.
1236 */
1237function walkCommand(
1238 node: Node,
1239 extraRedirects: Redirect[],
1240 innerCommands: SimpleCommand[],
1241 varScope: Map<string, string>,
1242): ParseForSecurityResult {
1243 const argv: string[] = []
1244 const envVars: { name: string; value: string }[] = []
1245 const redirects: Redirect[] = [...extraRedirects]
1246
1247 for (const child of node.children) {
1248 if (!child) continue
1249
1250 switch (child.type) {
1251 case 'variable_assignment': {
1252 const ev = walkVariableAssignment(child, innerCommands, varScope)
1253 if ('kind' in ev) return ev
1254 // SECURITY: Env-prefix assignments (`VAR=x cmd`) are command-local in
1255 // bash — VAR is only visible to `cmd` as an env var, NOT to
1256 // subsequent commands. Do NOT add to global varScope — that would
1257 // let `VAR=safe cmd1 && rm $VAR` resolve $VAR when bash has unset it.
1258 envVars.push({ name: ev.name, value: ev.value })
1259 break
1260 }
1261 case 'command_name': {
1262 const arg = walkArgument(
1263 child.children[0] ?? child,
1264 innerCommands,
1265 varScope,
1266 )
1267 if (typeof arg !== 'string') return arg
1268 argv.push(arg)
1269 break
1270 }
1271 case 'word':
1272 case 'number':
1273 case 'raw_string':
1274 case 'string':
1275 case 'concatenation':
1276 case 'arithmetic_expansion': {
1277 const arg = walkArgument(child, innerCommands, varScope)
1278 if (typeof arg !== 'string') return arg
1279 argv.push(arg)
1280 break
1281 }
1282 // NOTE: command_substitution as a BARE argument (not inside a string)
1283 // is intentionally NOT handled here — the $() output IS the argument,
1284 // and for path-sensitive commands (cd, rm, chmod) the placeholder would
1285 // hide the real path from downstream checks. `cd $(echo /etc)` must
1286 // stay too-complex so the path-check can't be bypassed. $() inside
1287 // strings ("Timer: $(date)") is handled in walkString where the output
1288 // is embedded in a longer string (safer).
1289 case 'simple_expansion': {
1290 // Bare `$VAR` as an argument. Tracked static vars return the ACTUAL
1291 // value (e.g. VAR=/etc → '/etc'). Values with IFS/glob chars or
1292 // placeholders reject. See resolveSimpleExpansion.
1293 const v = resolveSimpleExpansion(child, varScope, false)
1294 if (typeof v !== 'string') return v

Callers 1

collectCommandsFunction · 0.85

Calls 7

walkVariableAssignmentFunction · 0.85
walkArgumentFunction · 0.85
resolveSimpleExpansionFunction · 0.85
walkFileRedirectFunction · 0.85
walkHerestringRedirectFunction · 0.85
tooComplexFunction · 0.85
pushMethod · 0.45

Tested by

no test coverage detected