* Recurse into a command_substitution node's inner command(s). If the inner * command(s) parse cleanly (simple), add them to the innerCommands * accumulator and return null (success). If the inner command is itself * too-complex (e.g., nested arith expansion, process sub), return the error. * Th
( csNode: Node, innerCommands: SimpleCommand[], varScope: Map<string, string>, )
| 1372 | * (inner) — permission rules must match BOTH for the whole command to allow. |
| 1373 | */ |
| 1374 | function collectCommandSubstitution( |
| 1375 | csNode: Node, |
| 1376 | innerCommands: SimpleCommand[], |
| 1377 | varScope: Map<string, string>, |
| 1378 | ): ParseForSecurityResult | null { |
| 1379 | // Vars set BEFORE the $() are visible inside (bash subshell semantics), |
| 1380 | // but vars set INSIDE don't leak out. Pass a COPY of the outer scope so |
| 1381 | // inner assignments don't mutate the outer map. |
| 1382 | const innerScope = new Map(varScope) |
| 1383 | // command_substitution children: `$(` or `` ` ``, inner statement(s), `)` |
| 1384 | for (const child of csNode.children) { |
| 1385 | if (!child) continue |
| 1386 | if (child.type === '$(' || child.type === '`' || child.type === ')') { |
| 1387 | continue |
| 1388 | } |
| 1389 | const err = collectCommands(child, innerCommands, innerScope) |
| 1390 | if (err) return err |
| 1391 | } |
| 1392 | return null |
| 1393 | } |
| 1394 | |
| 1395 | /** |
| 1396 | * Convert an argument node to its literal string value. Quotes are resolved. |
no test coverage detected