Skip to content

DO NOT MERGE: combined check, batch b28 - #1127

Closed
jayden1711 wants to merge 21 commits into
mainfrom
combined-b28
Closed

jayden1711 wants to merge 21 commits into
mainfrom
combined-b28

Conversation

@jayden1711

Copy link
Copy Markdown
Owner

DO NOT MERGE. Combined check for batch b28: #1101 @62b020d6.

…ush (#993)

The tool guard caught only the exact --no-verify and -c core.hooksPath.
It now reads a push's words as git does: prefixes of --no-verify, config
that can carry the hooks path or run a push by another name (includes,
aliases, help.autocorrect) by -c, git config or GIT_CONFIG_*, environment
that gives a push other config or another repository's hooks, and pushes
that run no hook (send-pack, http-push, remote helpers). A git name that
isn't one of git's commands is looked up in config as git would (alias,
correction); a lookup that fails refuses.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…uses (#993)

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…ard's list (#993)

The change-reader lint counts ls-files, whatchanged and the diff plumbing
names in src/. They need no entry: git never lets an alias shadow them, so
a lookup finds nothing.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…ne's text (#993)

The push guard matched `env -` anywhere in the command text, so a quoted
argument that says it (git commit -m "fix env -i handling" && git push)
was refused. The shell matcher now records the options it strips from an
env wrapper, and the guard reads those, or `env -<opt>` as words of a
program it doesn't model (find -exec env -i ...).

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…it push and git config (#993)

`$(git --exec-path)/git-push --no-verify` and `/usr/lib/git-core/git-push
--no-verify` skip the pre-push hook (measured, git 2.43) and were allowed:
the guard only read a command named `git`. A program named git-push or
git-config (any path, .exe) is now read as that subcommand.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…a partial list (#993)

The push guard's hard-coded list of git commands that never push left
out about 70 of git's own (ls-files, diff-tree, diff-index, mergetool,
...), so a line that sets GIT_* or changes directory where the guard
can't follow refused them: `cd "$D" && git ls-files`, `GIT_PAGER=cat git
ls-files`, `GIT_TRACE=1 git diff-index HEAD`. Main allows these.

git never runs an alias for a name that is one of its commands (built
in, in its exec path, or a git-* program on PATH; measured, git 2.43),
so the guard now asks git: `git --list-cmds=main,others`. A line that
sets PATH trusts only `main`; one that moves the exec path, unsets or
gives env an option trusts only `builtins`. The static list stays for a
guard with no lookup, or a git that can't answer. exampleContext answers
the list from this machine's git, which needs no repository.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
With only the env wrapper's options read, `find . -exec env -i git push \;` went through and no test failed.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…es (#993)

The changelog said external git commands were unchanged while the head
refused `GIT_PAGER=cat git lfs ls-files` in the tool guard. It now lists
the ordinary lines an agent run newly refuses, and the design table
names git's own git-push program.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
… command position (#993)

The push guard took any argument whose basename was git as a git call,
and any word env followed by a dash-word as env's options. So
`cd "$D" && rm -rf vendor/git build`, `GIT_TRACE=1 make -C
third_party/git all`, `git grep env -- src && git push` and
`echo env -i && git push` were refused; main allows them.

A command's programs are now: itself after the wrappers the shell
matcher removes, each find -exec/-execdir/-ok command, and the command
a known runner (setsid, flock, strace, ...) runs. git, env's options and
git-send-pack / git-http-push / git-remote-* are read from those only,
so `find -exec /usr/lib/git-core/git-send-pack ...`, allowed before, is
refused.

The shell matcher now takes the value of a wrapper option that has one
(env -u NAME, -C DIR, nice -n N, ionice -c N, exec -a NAME, doas -u,
time -o) so the next word is the command, and splits env -S's command
line into words. The guard used to find git after such a value by
looking for it anywhere.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…s or moves PATH or the exec path (#993)

Any unset, export -n or env option made the push guard trust only git's
built-in commands, so `unset GIT_DIR; git submodule update --init`,
`unset FOO; git mergetool --tool-help` and `export -n FOO; git lfs
pull` were refused; main allows them. The list now narrows to `main`
only where the line sets or removes PATH, and to `builtins` where it
sets or removes GIT_EXEC_PATH or clears the environment (env -i, env -).

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…me the known gaps (#993)

The changelog said mergetool and lfs were unchanged and that the push guard refuses every spelling git reads; neither held. It now lists what was measured as newly refused, says that list is not a proof, and names the gaps that remain.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…he first git anywhere (#993)

Each known runner (setsid, flock, strace, taskset, chrt, nsenter, unshare,
systemd-run, runuser, ...) now has its options, the ones that take a value,
and its operands (flock's lock file, taskset's mask, chrt's priority). The
command is the first word after those, and only that word is read, so
`strace -f make -C third_party/git all`, `flock /tmp/l rm -rf vendor/git`
and `chronic rg env -i src && git push` are allowed again, while
`flock /tmp/git git push --no-verify` and `strace -o /tmp/git git push
--no-verify` are refused. timeout reads --kill-after/--signal and xargs
its long value options. Tests pin doas -u, time -o, env --split-string=,
env -uNAME and find -ok/-okdir.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…autocorrect (#993)

`git config alias.st` and `git config help.autocorrect` only print a
value. A `git config` with one name operand and only read options is a
read; a value, a write subcommand or option, or an option the guard
doesn't know is still refused.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…and the -c command-string gaps (#993)

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…ment rules (#993)

git config stops reading options at the first word that isn't one, so a
word after the name is a value even when it looks like an option: git
2.43 writes `git config core.hooksPath --global` as the value --global.
The round-4 check read that word as a read option and allowed the line,
and any `get` or `list` word anywhere made a write count as a read.

configUse now follows git's rules in one place: options end at the first
other word or `--`; that word is the subcommand (get/list read) or the
name; with no read action a second operand is a value. A table of 46
forms pins it.

Runner value options are checked against each program's option table:
systemd-run's -G is --collect (a flag) and it has no -s; ltrace's -L is
a flag and -D/-X take values; fakeroot -f/-b, unshare --map-users and
--monotonic, and systemd-run's path/socket/unit-timer properties take
values. Tests cover an attached value, --opt=value and a leading --.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
env's getopt ("+C:iS:u:v0") gives the first value letter in a cluster the
rest of the word, so `env -uCC git push --no-verify` unsets CC and runs
git (measured: `env -uCC echo` runs echo). The matcher's regex read any
cluster ending in u, C or S as taking the next word, so it took `git` as
the value and missed the push; both the tool guard and the whole hook
allowed it, where main refused it. Its unanchored -S match also split
`-uSSH_AUTH_SOCK` as `-S 'H_AUTH_SOCK'`.

envShort reads a cluster once, for the wrapper stripper and for the names
env removes; -i clears the environment only before the value letter.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…ns does (#993)

A git config short-option cluster is read by one reader, shared with env's:
flag letters continue the cluster and -f or -t takes the rest of the word or
the next one. -e among the flags edits in any position (-ez, -zef FILE, -et
bool), and -t is --type, so -t bool --get NAME reads.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…#993)

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
… --signals, --argv0, --decode-pids (#993)

strace 6.8's longopts give silent, silence and quiet an optional_argument,
so strace --silent git push runs git; signals, argv0 and decode-pids take a
required one. flock's -c and --command are not getopt options: flock reads
them after the lock file, where the none table already does.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
…lled program (#993)

A wrong entry in a runner's value table hides the command it runs. Each
installed runner is given each listed value option alone, with no command,
and must report a missing argument; systemd-run, runuser and ssh-agent are
read from their program files (getopt string, help text), never run.

Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
Signed-off-by: Jayden Vasquez <jaydenvasquez1711@gmail.com>
@jayden1711 jayden1711 closed this Oct 26, 2026
@jayden1711
jayden1711 deleted the combined-b28 branch October 26, 2026 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant