MCPcopy Create free account
hub / github.com/freecodexyz/free-code / isGitSafe

Function isGitSafe

src/tools/PowerShellTool/readOnlyValidation.ts:1584–1701  ·  view source on GitHub ↗
(args: string[])

Source from the content-addressed store, hash-verified

1582const DANGEROUS_GIT_SHORT_FLAGS_ATTACHED = ['-c', '-C']
1583
1584function isGitSafe(args: string[]): boolean {
1585 if (args.length === 0) {
1586 return true
1587 }
1588
1589 // SECURITY: Reject any arg containing `$` (variable reference). Bare
1590 // VariableExpressionAst positionals reach here as literal text ($env:SECRET,
1591 // $VAR). deriveSecurityFlags does not gate bare Variable args. The validator
1592 // sees `$VAR` as text; PowerShell expands it at runtime. Parser differential:
1593 // git diff $VAR where $VAR = '--output=/tmp/evil'
1594 // → validator sees positional '$VAR' → validateFlags passes
1595 // → PowerShell runs `git diff --output=/tmp/evil` → file write
1596 // This generalizes the ls-remote inline `$` guard below to all git subcommands.
1597 // Bash equivalent: BashTool blanket
1598 // `$` rejection at readOnlyValidation.ts:~1352. isGhSafe has the same guard.
1599 for (const arg of args) {
1600 if (arg.includes('$')) {
1601 return false
1602 }
1603 }
1604
1605 // Skip over global flags before the subcommand, rejecting dangerous ones.
1606 // Flags that take space-separated values must consume the next token so it
1607 // isn't mistaken for the subcommand (e.g. `git --namespace foo status`).
1608 let idx = 0
1609 while (idx < args.length) {
1610 const arg = args[idx]
1611 if (!arg || !arg.startsWith('-')) {
1612 break
1613 }
1614 // SECURITY: Attached-form short flags. `-ccore.pager=sh` splits on `=` to
1615 // `-ccore.pager`, which isn't in DANGEROUS_GIT_GLOBAL_FLAGS. Git accepts
1616 // `-c<name>=<value>` and `-C<path>` with no space. We must prefix-match.
1617 // Note: `--cached`, `--config-env`, etc. already fail startsWith('-c') at
1618 // position 1 (`-` ≠ `c`). The `!== '-'` guard only applies to `-c`
1619 // (git config keys never start with `-`, so `-c-key` is implausible).
1620 // It does NOT apply to `-C` — directory paths CAN start with `-`, so
1621 // `git -C-trap status` must reject. `git -ccore.pager=sh log` spawns a shell.
1622 for (const shortFlag of DANGEROUS_GIT_SHORT_FLAGS_ATTACHED) {
1623 if (
1624 arg.length > shortFlag.length &&
1625 arg.startsWith(shortFlag) &&
1626 (shortFlag === '-C' || arg[shortFlag.length] !== '-')
1627 ) {
1628 return false
1629 }
1630 }
1631 const hasInlineValue = arg.includes('=')
1632 const flagName = hasInlineValue ? arg.split('=')[0] || '' : arg
1633 if (DANGEROUS_GIT_GLOBAL_FLAGS.has(flagName)) {
1634 return false
1635 }
1636 // Consume the next token if the flag takes a separate value
1637 if (!hasInlineValue && GIT_GLOBAL_FLAGS_WITH_VALUES.has(flagName)) {
1638 idx += 2
1639 } else {
1640 idx++
1641 }

Callers 1

isExternalCommandSafeFunction · 0.85

Calls 2

validateFlagsFunction · 0.85
hasMethod · 0.45

Tested by

no test coverage detected