Hmbown/CodeWhale · error

classifier-approved Git read did not keep its subcommand in…

Error message

classifier-approved Git read did not keep its subcommand in argv[1]

What it means

This error is raised in `hardened_readonly_argv` when the subcommand found after the `--no-pager`/`-C` preamble is not one of the hardener-supported read-only subcommands (diff, log, show, status, ls-files, blame, grep). The guard enforces that only allowlisted Git reads, whose safety flags the hardener knows how to splice in, reach execution; anything else is rejected instead of run unhardened.

Solutions

  1. Use one of the supported read-only subcommands: diff, log, show, status, ls-files, blame, grep
  2. For other Git reads, fall back to the non-hardened (permission-prompted) shell path or another tool
  3. If a new subcommand should be supported, add it to the match in hardened_readonly_argv together with the hardening flags it needs

Example fix

// before
run_readonly("git remote -v")
// after
run_readonly("git ls-files") // or use the standard permissioned shell path
Defensive patterns

Strategy: validation

Validate before calling

const GIT_READONLY_SUBCOMMANDS: &[&str] =
    &["diff", "log", "show", "status", "ls-files", "blame", "grep"];
fn git_subcommand_allowed(cmd: &str) -> bool {
    let argv = shell_words::split(cmd).unwrap_or_default();
    let mut i = 1;
    while matches!(argv.get(i).map(String::as_str), Some("--no-pager") | Some("-C")) {
        i += if argv.get(i).map(String::as_str) == Some("-C") { 2 } else { 1 };
    }
    matches!(argv.get(i).map(String::as_str), Some(s) if GIT_READONLY_SUBCOMMANDS.contains(&s))
}

Prevention

When it happens

Trigger: Issuing a classifier-approved read-only `git` command whose subcommand is outside the allowlist, e.g. `git fetch`, `git remote -v`, `git add -n`, or `git worktree list`. The classifier may have passed the command as a read, but the argv hardener independently rejects unsupported subcommands.

Common situations: Developers assuming any read-looking Git command is allowed (`git remote -v`, `git branch -a`, `git config --get`); version drift where the classifier allowlist and the hardener's match arm diverge; typos in the subcommand token.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/2e9502c36bfd8ace. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/shell.rs:4236

                argv.splice(
                    at..at,
                    ["--no-ext-diff".to_string(), "--no-textconv".to_string()],
                );
            }
            "log" | "show" => {
                let at = subcommand_index + 1;
                argv.splice(
                    at..at,
                    [
                        "--no-ext-diff".to_string(),
                        "--no-textconv".to_string(),
                        "--no-show-signature".to_string(),
                    ],
                );
            }
            "status" | "ls-files" | "blame" | "grep" => {}
            _ => {
                return Err(anyhow!(
                    "classifier-approved Git read did not keep its subcommand in argv[1]"
                ));
            }
        }
    }

    let program = argv.remove(0);
    Ok((program, argv))
}

fn enforce_readonly_workspace_operands(
    command: &str,
    workspace: &std::path::Path,
    effective_cwd: &std::path::Path,
) -> Result<(), ToolError> {
    let argv = shell_words::split(&normalize_windows_command_paths(command)).map_err(|error| {
        ToolError::invalid_input(format!(
            "Could not parse read-only command arguments: {error}"

View on GitHub (pinned to 73e0f67d83)