Send()-ing Myself Belated Christmas Gifts: GitHub.com's Environment Variables & GHES Shell
A December 26 bug hunt that started as a lark ended up leaking ~2 MB of GitHub.com environment variables (including access keys and secrets) and, on GitHub Enterprise Server, chained to full RCE.
Table of Contents
Short version: while poking at GitHub Enterprise Server (GHES) for an unrelated reason the day after Christmas, I noticed an unvalidated Kernel#send() call in the organization repository settings component. I expected it to be mildly useful, at most leaking file paths or affecting my own organisation. Production GitHub.com proved otherwise.
The primitive
The component in app/components/organizations/settings/repository_items_component.rb forwards a user-controlled rid_key parameter directly to send() on the repository dependency object. Ruby’s Kernel#send dispatches the argument as a method name, which (with the right object graph) gives you a read primitive over arbitrary methods of the target object.
The leak
Chaining send() through the right method on GHES, and eventually on production GitHub.com, produced a response body containing roughly 2 MB of environment variables belonging to the git worker process: a list of access keys, secrets, and internal configuration.
Why so many env vars?
GitHub.com spawns git processes with a full copy of the parent environment (1,220 variables on the system I measured). The fix here is narrower than “patch the send”; it’s also to stop handing the world to every spawned git.
On GHES: from read to shell
On GHES specifically, the leaked environment contained a Marshal-secret variable that, combined with a separate Marshal.load sink, chains to full remote code execution. Production GitHub.com doesn’t set this variable, so the chain stops at “catastrophic information disclosure” there.
Disclosure
Reported through the GitHub Bug Bounty programme. The Hubbers working over the Christmas/New Year window turned the fix around quickly. Apologies and thanks to the team for the disrupted holiday.