( input: z.infer<typeof BashTool.inputSchema>, compoundCommandHasCd: boolean, )
| 1874 | * @returns PermissionResult indicating whether the command is read-only |
| 1875 | */ |
| 1876 | export function checkReadOnlyConstraints( |
| 1877 | input: z.infer<typeof BashTool.inputSchema>, |
| 1878 | compoundCommandHasCd: boolean, |
| 1879 | ): PermissionResult { |
| 1880 | const { command } = input |
| 1881 | |
| 1882 | // Detect if the command is not parseable and return early |
| 1883 | const result = tryParseShellCommand(command, env => `$${env}`) |
| 1884 | if (!result.success) { |
| 1885 | return { |
| 1886 | behavior: 'passthrough', |
| 1887 | message: 'Command cannot be parsed, requires further permission checks', |
| 1888 | } |
| 1889 | } |
| 1890 | |
| 1891 | // Check the original command for safety before splitting |
| 1892 | // This is important because splitCommand_DEPRECATED may transform the command |
| 1893 | // (e.g., ${VAR} becomes $VAR) |
| 1894 | if (bashCommandIsSafe_DEPRECATED(command).behavior !== 'passthrough') { |
| 1895 | return { |
| 1896 | behavior: 'passthrough', |
| 1897 | message: 'Command is not read-only, requires further permission checks', |
| 1898 | } |
| 1899 | } |
| 1900 | |
| 1901 | // Check for Windows UNC paths in the original command before transformation |
| 1902 | // This must be done before splitCommand_DEPRECATED because splitCommand_DEPRECATED may transform backslashes |
| 1903 | if (containsVulnerableUncPath(command)) { |
| 1904 | return { |
| 1905 | behavior: 'ask', |
| 1906 | message: |
| 1907 | 'Command contains Windows UNC path that could be vulnerable to WebDAV attacks', |
| 1908 | } |
| 1909 | } |
| 1910 | |
| 1911 | // Check once if any subcommand is a git command (used for multiple security checks below) |
| 1912 | const hasGitCommand = commandHasAnyGit(command) |
| 1913 | |
| 1914 | // SECURITY: Block compound commands that have both cd AND git |
| 1915 | // This prevents sandbox escape via: cd /malicious/dir && git status |
| 1916 | // where the malicious directory contains fake git hooks that execute arbitrary code. |
| 1917 | if (compoundCommandHasCd && hasGitCommand) { |
| 1918 | return { |
| 1919 | behavior: 'passthrough', |
| 1920 | message: |
| 1921 | 'Compound commands with cd and git require permission checks for enhanced security', |
| 1922 | } |
| 1923 | } |
| 1924 | |
| 1925 | // SECURITY: Block git commands if the current directory looks like a bare/exploited git repo |
| 1926 | // This prevents sandbox escape when an attacker has: |
| 1927 | // 1. Deleted .git/HEAD to invalidate the normal git directory |
| 1928 | // 2. Created hooks/pre-commit or other git-internal files in the current directory |
| 1929 | // Git would then treat the cwd as the git directory and execute malicious hooks. |
| 1930 | if (hasGitCommand && isCurrentDirectoryBareGitRepo()) { |
| 1931 | return { |
| 1932 | behavior: 'passthrough', |
| 1933 | message: |
no test coverage detected