{"thread":{"id":"64840","subject":"Detecting source of a push in a pre-receive hook","startedAt":"2026-01-20T20:46:04Z","lastAt":"2026-01-21T05:31:54Z","messageCount":4,"participants":["Chris Packham","rsbecker@nexbridge.com","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"534289","messageId":"CAFOYHZDcFJBiZwmposZVGmymmRz1XOaXP8iCRgTDVcsWPTH=6g@mail.gmail.com","threadId":"64840","inReplyTo":"CAFOYHZDnXQOcDmzwf1WRpZpNRAs-R2YOBh3ru0mr0ffrMLB=9Q@mail.gmail.com","subject":"Detecting source of a push in a pre-receive hook","fromName":"Chris Packham","fromEmail":"judge.packham@gmail.com","sentAt":"2026-01-20T20:45:51Z","receivedAt":"2026-01-20T20:46:04Z","isPatch":false,"sender":{"key":"judge.packham@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155667?v=4"},"body":"Hi Git,\n\nAt $dayjob we're moving from a mix of plain git repositories on a\nserver accessed via ssh with a secondary Gerrit server tacked on the\nside for code review to using the Gerrit server as the primary source\nof truth.\n\nSo that people don't have to update origin.url for all their local\nrepositories, we're using the Gerrit replication plugin to keep the\nold server in sync (and will likely do so for the foreseeable future).\nWe have installed a pre-receive hook for the migrated repositories on\nthe old server that rejects pushes from anyone except the user that\nthe replication runs as.\n\nFor various reasons we also have a CI system that pushes some things\n(mostly tags but some automated merge commits as well) that runs as\nthe same user. We'd really like to be able to have the pre-receive\nhook reject pushes from the CI system but allow them from the Gerrit\nserver. Does the pre-receive hook have any way of knowing the source\nof a push operation?\n\nThanks,\nChris\n"},{"id":"534302","messageId":"00ce01dc8a57$c3e19140$4ba4b3c0$@nexbridge.com","threadId":"64840","inReplyTo":"CAFOYHZDcFJBiZwmposZVGmymmRz1XOaXP8iCRgTDVcsWPTH=6g@mail.gmail.com","subject":"RE: Detecting source of a push in a pre-receive hook","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2026-01-20T21:57:20Z","receivedAt":"2026-01-20T21:57:33Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On January 20, 2026 3:46 PM, Chris Packham wrote:\n>At $dayjob we're moving from a mix of plain git repositories on a server accessed via\n>ssh with a secondary Gerrit server tacked on the side for code review to using the\n>Gerrit server as the primary source of truth.\n>\n>So that people don't have to update origin.url for all their local repositories, we're\n>using the Gerrit replication plugin to keep the old server in sync (and will likely do so\n>for the foreseeable future).\n>We have installed a pre-receive hook for the migrated repositories on the old server\n>that rejects pushes from anyone except the user that the replication runs as.\n>\n>For various reasons we also have a CI system that pushes some things (mostly tags\n>but some automated merge commits as well) that runs as the same user. We'd\n>really like to be able to have the pre-receive hook reject pushes from the CI system\n>but allow them from the Gerrit server. Does the pre-receive hook have any way of\n>knowing the source of a push operation?\n\nLet me first say that I have not tried this, but had a similar request on an exotic\nplatform. Let me then say that the next paragraph contains likely very bad ideas.\n\nYou *might* be able to as the OS what the end point is for stdin to your hook. I\nam in no way certain that git passes the originating pipe to you, but some systems\nmay allow this. Some other systems allow you to walk though process context\ngiven the originating pipe, but that's probably less likely to work. Other OS\nenvironments allow you to install hooks into the OS to track pipe operations.\nIf any of this even slightly works, it is highly unlikely to be portable.\n\nPerhaps a better way (more reliable, easier, portable) is to use a firewall to\nblock the requests from the CI system to a specific port your git subsystem\nis listening on.\n\nMy $0.0002 thoughts,\nRandall\n\n"},{"id":"534308","messageId":"20260121052705.GA567009@coredump.intra.peff.net","threadId":"64840","inReplyTo":"CAFOYHZDcFJBiZwmposZVGmymmRz1XOaXP8iCRgTDVcsWPTH=6g@mail.gmail.com","subject":"Re: Detecting source of a push in a pre-receive hook","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-01-21T05:27:05Z","receivedAt":"2026-01-21T05:27:06Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 21, 2026 at 09:45:51AM +1300, Chris Packham wrote:\n\n> For various reasons we also have a CI system that pushes some things\n> (mostly tags but some automated merge commits as well) that runs as\n> the same user. We'd really like to be able to have the pre-receive\n> hook reject pushes from the CI system but allow them from the Gerrit\n> server. Does the pre-receive hook have any way of knowing the source\n> of a push operation?\n\nGit doesn't do any authentication or know about the push sources itself;\nit just sees that stdin/stdout have somehow been hooked up to a client.\n\nBut the protocol layer that does that hooking up sometimes leaves\ninformation in the environment. If clients are connecting over ssh, for\nexample, then you'll probably have an $SSH_CLIENT variable set. For\nHTTP, you'd probably get $REMOTE_ADDR, I think.\n\nHow do you want to identify the CI system versus the Gerrit system? The\nsuggestions above would look at the source IP. If you're using ssh and\nhave different keys for each incoming entity, you could probably add an\n\"environment=\" field to your authorized_keys file, and then check that\nfield in the pre-receive hook (or if you wanted, even use a \"command=\"\nfield to restrict git-receive-pack to only specific keys).\n\nOver HTTP, you'd have to look at how authentication is done for the two\nentities. I _think_ you reliably get $REMOTE_USER if there was the usual\nHTTP auth done, and you could check that. But you could probably also do\nsome server-specific magic to reject receive-pack quests. There are some\nhints for Apache in the git-http-backend manpage, but you might also be\nable to copy ideas from the test config we use in t/lib-httpd.\n\n-Peff\n"},{"id":"534311","messageId":"20260121053153.GA567894@coredump.intra.peff.net","threadId":"64840","inReplyTo":"20260121052705.GA567009@coredump.intra.peff.net","subject":"Re: Detecting source of a push in a pre-receive hook","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-01-21T05:31:53Z","receivedAt":"2026-01-21T05:31:54Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 21, 2026 at 12:27:05AM -0500, Jeff King wrote:\n\n> But the protocol layer that does that hooking up sometimes leaves\n> information in the environment. If clients are connecting over ssh, for\n> example, then you'll probably have an $SSH_CLIENT variable set. For\n> HTTP, you'd probably get $REMOTE_ADDR, I think.\n\nBTW, one easy way to investigate this is to just put:\n\n  env >&2\n\ninto your pre-receive, and then try a push. We forward stderr from the\nhook back to the client, so you can see what the server has available in\nthe environment.\n\n-Peff\n"}]}