(command: string)
| 241 | * because stripSafeWrappers won't strip RUN. |
| 242 | */ |
| 243 | export function getFirstWordPrefix(command: string): string | null { |
| 244 | const tokens = command.trim().split(/\s+/).filter(Boolean) |
| 245 | |
| 246 | let i = 0 |
| 247 | while (i < tokens.length && ENV_VAR_ASSIGN_RE.test(tokens[i]!)) { |
| 248 | const varName = tokens[i]!.split('=')[0]! |
| 249 | const isAntOnlySafe = |
| 250 | process.env.USER_TYPE === 'ant' && ANT_ONLY_SAFE_ENV_VARS.has(varName) |
| 251 | if (!SAFE_ENV_VARS.has(varName) && !isAntOnlySafe) { |
| 252 | return null |
| 253 | } |
| 254 | i++ |
| 255 | } |
| 256 | |
| 257 | const cmd = tokens[i] |
| 258 | if (!cmd) return null |
| 259 | // Same shape check as the subcommand regex in getSimpleCommandPrefix: |
| 260 | // rejects paths (./script.sh, /usr/bin/python), flags, numbers, filenames. |
| 261 | if (!/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(cmd)) return null |
| 262 | if (BARE_SHELL_PREFIXES.has(cmd)) return null |
| 263 | return cmd |
| 264 | } |
| 265 | |
| 266 | function suggestionForExactCommand(command: string): PermissionUpdate[] { |
| 267 | // Heredoc commands contain multi-line content that changes each invocation, |
no test coverage detected