* Checks if a redirection target contains shell expansion syntax that could * bypass path validation. These require manual approval for security. * * Design invariant: for every string redirect target, EITHER isSimpleTarget * is TRUE (→ captured → path-validated) OR hasDangerousExpansion is TRUE
(target: ParseEntry | undefined)
| 828 | * rejects (except the empty string which is handled separately). |
| 829 | */ |
| 830 | function hasDangerousExpansion(target: ParseEntry | undefined): boolean { |
| 831 | // shell-quote parses unquoted globs as {op:'glob', pattern:'...'} objects, |
| 832 | // not strings. `> *.sh` as a redirect target expands at runtime (single match |
| 833 | // → overwrite, multiple → ambiguous-redirect error). Flag these as dangerous. |
| 834 | if (typeof target === 'object' && target !== null && 'op' in target) { |
| 835 | if (target.op === 'glob') return true |
| 836 | return false |
| 837 | } |
| 838 | if (typeof target !== 'string') return false |
| 839 | if (target.length === 0) return false |
| 840 | return ( |
| 841 | target.includes('$') || |
| 842 | target.includes('%') || |
| 843 | target.includes('`') || // Backtick substitution (was only in isSimpleTarget) |
| 844 | target.includes('*') || // Glob (was only in isSimpleTarget) |
| 845 | target.includes('?') || // Glob (was only in isSimpleTarget) |
| 846 | target.includes('[') || // Glob class (was only in isSimpleTarget) |
| 847 | target.includes('{') || // Brace expansion (was only in isSimpleTarget) |
| 848 | target.startsWith('!') || // History expansion (was only in isSimpleTarget) |
| 849 | target.startsWith('=') || // Zsh equals expansion (=cmd -> /path/to/cmd) |
| 850 | // ALL tilde-prefixed targets. Previously `~` and `~/path` were carved out |
| 851 | // with a comment claiming "handled by expandTilde" — but expandTilde only |
| 852 | // runs via validateOutputRedirections(redirections), and for `~/path` the |
| 853 | // redirections array is EMPTY (isSimpleTarget rejected it, so it was never |
| 854 | // pushed). The carve-out created a gap where `> ~/.bashrc` was neither |
| 855 | // captured nor flagged. See bug_007 / bug_022. |
| 856 | target.startsWith('~') |
| 857 | ) |
| 858 | } |
| 859 | |
| 860 | function handleRedirection( |
| 861 | part: ParseEntry, |
no outgoing calls
no test coverage detected