While building a Java REST API on my Linux (Fedora) machine, I noticed something bizarre on my GitHub repository page: right next to my profile picture in the Contributors sidebar, there was an unknown user (@wroc), whose account was created back in 2015 and had no recent activity.
The most intriguing detail? My local hostname/username on Fedora when I first initialized the project was wroc.
That coincidence triggered a few architecture and security questions:
- How did a user who never had access to my repository officially appear as a code contributor?
- If their account was linked to the commit, did GitHub's backend return real account metadata in the API response without their authentication?
- How far does this behavior go if I intentionally test it against another account?
This article documents my step-by-step investigation—inspecting raw Git objects, dissecting GitHub REST API JSON payloads, decoding Base64 Global Node IDs, and running a practical Proof of Concept (PoC).
1. Inspecting the Raw Git Object (git cat-file)
The first step was checking what was actually recorded locally in the repository's initial commits (specifically commit b1a5ca0).
To inspect the raw payload that Git sends over the wire during a git push, without any UI formatting, we use git cat-file -p:
git cat-file -p b1a5ca0
The output is surprisingly simple:
tree d3e2ab9087f6ccb4a141f7d368711233f879867d
author wroc <wroc@users.noreply.github.com> 1790719762 -0300
committer wroc <wroc@users.noreply.github.com> 1790719762 -0300
chore: initialize project structure and IDE configurations
When you run git commit, Git operates 100% offline. It makes no network requests, verifies no SSH keys, and does not validate whether you actually own that email address. It simply writes a plain-text string inside .git/objects/. At the time, my local Git config combined my Fedora hostname (wroc) with GitHub's noreply domain (wroc@users.noreply.github.com).
So what happens when we push this plain-text object to GitHub's servers via a git push authenticated with my own SSH key (lipebackend)?
2. What Does GitHub's API Return in the Response?
Querying GitHub's REST API directly for that specific commit:
curl -sL https://api.github.com/repos/lipebackend/api-rest/commits/b1a5ca0
We get the following JSON payload back from GitHub's backend:
{
"sha": "b1a5ca0edc8b69be88b91a67b4bd5d63543b8f90",
"node_id": "C_kwDOUzptmtoAKGIxYTVjYTBlZGM4YjY5YmU4OGI5MWE2N2I0YmQ1ZDYzNTQzYjhmOTA",
"commit": {
"author": {
"name": "wroc",
"email": "wroc@users.noreply.github.com",
"date": "2026-09-29T22:09:22Z"
},
"committer": {
"name": "wroc",
"email": "wroc@users.noreply.github.com",
"date": "2026-09-29T22:09:22Z"
},
"message": "chore: initialize project structure and IDE configurations",
"verification": {
"verified": false,
"reason": "unsigned",
"signature": null,
"payload": null
}
},
"author": {
"login": "wroc",
"id": 11420820,
"node_id": "MDQ6VXNlcjExNDIwODIw",
"avatar_url": "https://avatars.githubusercontent.com/u/11420820?v=4",
"url": "https://api.github.com/users/wroc",
"html_url": "https://github.com/wroc",
"repos_url": "https://api.github.com/users/wroc/repos",
"type": "User",
"user_view_type": "public",
"site_admin": false
}
}
Looking closely at this API response raises three fascinating software engineering and security questions:
- I only pushed a plain-text string (
wroc@users.noreply.github.com), yet GitHub's server returned a full"author"object containing the user's real internal database ID (11420820), theiravatar_url, and a Base64-encodednode_id(MDQ6VXNlcjExNDIwODIw). - When querying the user's public profile at
[https://api.github.com/users/wroc](https://api.github.com/users/wroc), their"email"field isnull! How did GitHub link the email if the public profile states"email": null? - Why is
node_idencoded in Base64?
3. Why is node_id in Base64? (MDQ6VXNlcjExNDIwODIw)
If we decode the "node_id": "MDQ6VXNlcjExNDIwODIw" field in a Linux terminal:
echo "MDQ6VXNlcjExNDIwODIw" | base64 -d
# Output: 04:User11420820
Why did GitHub engineers encode 04:User11420820 in Base64? It wasn't for encryption—it was a database architecture and API evolution decision driven by the GraphQL Relay Specification:
- In GitHub's relational database (MySQL), each table has its own sequential primary key (
id). There is anid = 11420820in theuserstable, but there can also be anid = 11420820in therepositoriesorissuestables. - When GitHub introduced its GraphQL API (v4), it needed a globally unique identifier (Global Node ID) so a generic
node(id: "...")query would know exactly which table toSELECTfrom. - Their initial solution combined the type length + entity name + primary key:
04:User11420820. -
Why Base64? To create an Opaque Identifier (Opaque Token), discouraging clients from doing
split(":")in their code and allowing GitHub to change the underlying structure in the future without breaking API contracts.
And GitHub actually did change it! Compare the node_id from the 2015 wroc account (MDQ6VXNlcjExNDIwODIw — plain text in Base64) with the node_id from my newer lipebackend account (U_kgDOE_lvuA — serialized in binary MessagePack + Base64).
4. How Did GitHub Link the Account if "email": null in the Public API?
If you query [https://api.github.com/users/wroc](https://api.github.com/users/wroc) (or my own profile [https://api.github.com/users/lipebackend](https://api.github.com/users/lipebackend)), you will see:
{
"login": "wroc",
"id": 11420820,
"node_id": "MDQ6VXNlcjExNDIwODIw",
"email": null,
"created_at": "2015-03-11T08:40:54Z"
}
The "email": null field in the public API DTO only means the user chose not to display a public email address on their profile bio. However, under the hood, when a commit arrives via git push, GitHub's backend performs internal identity resolution:
-
Legacy
@users.noreply.github.comRouting Rule: Accounts created before 2017 used the<username>@users.noreply.github.comformat (newer accounts use<id>+<username>@users.noreply.github.comspecifically to prevent collisions or broken links when changing@username). When GitHub parseswroc@users.noreply.github.comin the commit, it extracts thewroclogin and queries the users table directly (WHERE login = ?). -
Internal Private Email Table (The "Identity Oracle"): Even if you don't use
@users.noreply.github.comand instead put someone's real personal email in the commit, GitHub's backend performs an internalJOINagainst its private registered emails table (user_emails)—even if that email is marked as private on their profile—and attaches the owner's public user object to the commit response!
Here is the complete flow happening behind the scenes:
[1. COMMIT TIME - 100% Offline on Local Machine]
git commit writes plain text into .git/objects:
author: "wroc <wroc@users.noreply.github.com>" (No password / No SSH key)
|
v
[2. PUSH TIME - Authenticates Transport, NOT the Author!]
git push connects using "lipebackend" SSH key
GitHub server validates: "lipebackend owns the repo, push accepted!"
|
v
[3. AUTOMATIC BACKEND JOIN ON GITHUB]
GitHub parses commit text and runs a SELECT on its Internal User Database
Matches the real "wroc" record (id: 11420820) without requiring a signature!
|
v
[4. API RESPONSE / WEB UI]
GET /repos/lipebackend/api-rest/commits/b1a5ca0
Returns JSON with real "wroc" account metadata and adds them to Contributors!
5. Proof of Concept (PoC): Testing in Practice (Anonymized Data)
To prove that any email registered on GitHub (even hidden with "email": null on the public profile) would be resolved and attached to my repository without any authentication from the other party, I ran a controlled test with a fellow developer's permission (anonymized below as dev-example / contact@example.dev).
First, we verify that their email is hidden on their public profile ([https://api.github.com/users/dev-example](https://api.github.com/users/dev-example)):
curl -s https://api.github.com/users/dev-example | grep -E '"(login|id|node_id|email)"'
"login": "dev-example",
"id": 9876543,
"node_id": "MDQ6VXNlcjk4NzY1NDM=",
"email": null,
Next, we create an empty commit (--allow-empty) in our repository by overriding Git environment variables and pushing to origin:
GIT_AUTHOR_NAME="dev-example" \
GIT_AUTHOR_EMAIL="contact@example.dev" \
GIT_COMMITTER_NAME="dev-example" \
GIT_COMMITTER_EMAIL="contact@example.dev" \
git commit --allow-empty -m "chore: test commit author resolution" && git push origin HEAD
We immediately query the newly created commit via GitHub's API:
curl -sL https://api.github.com/repos/lipebackend/api-rest/commits/<commit-sha>
And GitHub's backend immediately responds with the real account linked:
{
"sha": "eaf17be95da2a3210efba894140287493da7b7a4",
"commit": {
"author": {
"name": "dev-example",
"email": "contact@example.dev",
"date": "2026-10-17T02:26:52Z"
},
"message": "chore: test commit author resolution",
"verification": {
"verified": false,
"reason": "unsigned"
}
},
"author": {
"login": "dev-example",
"id": 9876543,
"node_id": "MDQ6VXNlcjk4NzY1NDM=",
"avatar_url": "https://avatars.githubusercontent.com/u/9876543?v=4",
"url": "https://api.github.com/users/dev-example",
"html_url": "https://github.com/dev-example",
"type": "User"
}
}
6. Security Implications (AppSec, OSINT, and Bug Bounty)
While Git treats this as expected behavior (since Linus Torvalds designed Git as a decentralized system where maintainers apply emailed patches while preserving the original Author), the way GitHub resolves and links user accounts without enforcing cryptographic signatures by default opens up real-world attack vectors:
-
Email-to-Account Enumeration Oracle (OSINT): Even if a user sets
"email": nullon their public GitHub profile, anyone who possesses an email address can create a dummy commit in a private repository, push it, and inspect the API response (or Web UI) to unmask the exact GitHub account (login,id,avatar_url) tied to that private email. - Commit & Contributor Spoofing: Malicious repositories frequently inject commits using the email addresses of high-profile developers into their main branch so GitHub displays their official avatars and profiles under the Contributors tab, manufacturing false credibility for supply-chain or social engineering attacks.
-
Third-Party Integration Traps (Where Real Bug Bounties Live): GitHub itself documents this behavior as Known Issue / By Design because it exposes the
"verification": { "verified": false, "reason": "unsigned" }block. However, numerous third-party CI/CD tools, deployment bots, and enterprise integrations consume GitHub's Commits API and blindly trustresponse.author.login(orresponse.author.id), assuming GitHub has already authenticated the author's identity—completely forgetting to check whethercommit.verification.verified === true!
7. How to Protect Yourself
As a software engineer and architect, there are three essential layers of defense:
-
Cryptographically sign all your commits (SSH or GPG Signing): Configure your SSH or GPG key in Git (
git config --global commit.gpgsign true) so all your legitimate commits return"verified": trueand display the green Verified badge on GitHub. - Enable Vigilant Mode on GitHub: Go to Settings → SSH and GPG keys → Vigilant mode and check "Flag unsigned commits as unverified". Any commit spoofing your email without your cryptographic signature will explicitly display an Unverified warning badge.
-
If you build integrations using GitHub's API: Never trust a commit's
author.loginorauthor.idfields for authorization or security decisions without strictly validating thatcommit.verification.verified === truefirst.
Top comments (1)
Great writeup, and a good reminder that the author line in a commit is just a string Git trusts completely. Setting
user.useConfigOnly = truestops Git from guessing from your hostname, and GitHub's vigilant mode flags unsigned commits claiming to be you as Unverified. If you rewrite those commits, I'd be curious how fast the Contributors sidebar catches up.