git --end-of-options Git's --end-of-options flag, introduced in version 2.24.0 in November 2019, provides a way to separate options from revisions in commands like git log, addressing argument injection vulnerabilities (CWE-88) that arise when untrusted strings are passed as arguments. The flag is distinct from --, which git repurposed to separate revisions from pathspecs, and support for it was added to subcommands incrementally, with git rev-parse receiving it in 2.30.0 and git checkout and git reset in 2.43.1 in February 2024. I was reading through the fix for a package manager CVE last week and ran into a git flag I’d somehow never noticed: --end-of-options . My first reaction was that some LLM had hallucinated it, but it’s documented in gitcli 7 https://git-scm.com/docs/gitcli , it was added in git 2.24.0 in November 2019, and it exists because git had already used -- for something else.In most Unix tools -- marks the end of option parsing, so rm -- -f removes a file called -f rather than passing the force flag. Git had repurposed -- early on to separate revisions from pathspecs, because git log foo on its own is ambiguous between a branch named foo and a file named foo and one of the two readings needed a marker: git log main -- README.md means commits on main touching that file. That left the revision position with no terminator, so if a script runs git log "$rev" and $rev starts with a dash, git parses it as an option. From the commit that introduced https://github.com/git/git/commit/19e8789b236dfe33667747d5523d6689bb59b5ef --end-of-options : But that doesn’t work for the revision parser, because -- is already meaningful there: it separates revisions from pathspecs. So we need some other marker to separate options from revisions. -- and --end-of-options are different things in git, and treating them as interchangeable is a mistake I’ve now seen in several places. Putting -- before a URL in git clone -- "$url" works, because clone follows the POSIX convention. A trailing -- after a ref, as in git checkout "$ref" -- , marks $ref as a revision rather than a filename but still lets it be read as an option first. Passing an untrusted revision safely means writing git log --end-of-options "$rev" -- "$path" , with both markers doing separate jobs. Support for the new flag arrived per subcommand rather than all at once: git rev-parse only got it in 2.30.0 https://github.com/git/git/commit/3a1f91cfd9 , a year after the initial release, because it has its own hand-rolled argument parser, and git checkout and git reset rejected it until 2.43.1 https://github.com/git/git/commit/9385174627 in February 2024 because they parse -- themselves and the initial implementation left --end-of-options in the argument list where their parsers rejected it. Argument injection Git, hg, and ssh all ship options whose documented purpose is to run a command the caller names. git clone accepts --upload-pack=