Expand description
Hardened argv construction for the git write verbs (ADR-108).
Every caller-supplied value that can reach std::process::Command::args
for git.commit / git.branch / git.push passes through this module
first. Nothing here ever touches a shell: Command::new("git") spawns the
binary directly and .args([...]) passes each element as one literal,
unparsed argv entry — there is no string interpolation anywhere in this
crate’s write path for a caller-supplied value to escape.
This module owns exactly two responsibilities, both binding conditions of ADR-108’s Fork (b) resolution:
- Validation on every caller-supplied string before it can reach an argv
array. Commit paths use Git’s internally-added
:(literal)pathspec magic so valid filesystem names are not mistaken for caller-controlled pathspec syntax. - A fixed subcommand + flag allowlist — the
build_*_argvfunctions below are the only argv shapes the write handlers ever construct.
Force-push is rejected unconditionally by reject_force: no code path
in this module can produce --force, -f, or --force-with-lease in a
push argv, regardless of caller input or Gate policy (ADR-108 hard rule
1). This module is scoped for isolated, dedicated adversarial review per
ADR-108’s binding requirement — keep new git-write argv construction here,
not inlined into the handlers.
Enums§
- GitArg
Error - Everything that can go wrong constructing a git write argv. Every variant carries enough context to build a caller-facing error without ever echoing back characters that were rejected specifically because they were suspicious (the raw value is still included for legitimate debugging – none of the rejected classes here are secret-shaped).
Constants§
- MAX_
AUTHOR_ LEN - MAX_
MESSAGE_ LEN - MAX_
PATH_ LEN - MAX_
REF_ LEN - Maximum lengths, chosen generously above any real git identifier while still bounding argv/memory size against a malicious caller.
- MAX_
REMOTE_ LEN
Functions§
- build_
add_ argv - Builds the argv for the
git addpre-stage step ofgit.commitwhenpathsis non-empty. Fixed shape:["add", "--", literal-pathspecs...]. - build_
branch_ argv - Builds the argv for
git branch:["branch", "--", name]or["branch", "--", name, from]. - build_
commit_ argv - Builds the argv for
git commit. - build_
push_ argv - Builds the argv for
git push:["push", "--", remote, branch]. Never carries a force flag – seereject_force, which handlers must call before reaching this function. - reject_
force - ADR-108 hard rule 1: force-push is always denied, unconditionally, at the
handler – not left to Gate policy.
force: Some(true)(an explicit, loud request) is rejected; absent orSome(false)proceeds normally. There is no argv path anywhere in this module that can add a force flag. - validate_
author - Validates the
authorargument. Bound into a single--author=<value>argv token (seebuild_commit_argv), so a leading dash insidevaluecannot itself become a new flag – rejected anyway, defensively, since a concatenated--author=--upload-pack=xvalue has no legitimate reason to start with-. - validate_
commit_ path - Validates one entry of
git.commit’spathsargument as a bounded, repository-relative filename. Git parses path arguments as pathspecs even after--, sobuild_add_argvandbuild_commit_argvprepend the fixed, internally-constructed:(literal)signature after validation. Caller text such as:(top),*,?, brackets, leading dashes, control characters, and Unicode therefore remains filename text rather than Git syntax. NUL is rejected because operating-system argv cannot represent it. - validate_
message - Validates the commit message. Passed to git as a single argv element
bound to
-m’s value slot, so leading-is not an injection vector here (unlike ref/remote/path names, which can appear as bare positional argv entries) – only NUL bytes (illegal in a process argv on every target platform) and an unreasonable length are rejected. - validate_
ref_ name - Validates a branch/ref-shaped identifier:
name(git.branch),from(git.branch’s optional start point), andbranch(git.push’s target ref). Deliberately more restrictive than git’s owncheck-ref-format– this only needs to admit the identifiers a legitimate caller would ever pass, not the full ref grammar. - validate_
remote_ name - Validates the
remoteargument (git.push). Narrower than a ref name – remote names never contain/. - validate_
repo_ path - Validates the
repoargument shared by all three write verbs: must be an absolute local path containing a.gitentry (mirrorsgit.digest’s local-source validation insrc/source.rs).