Issue-Close Spoofing Persists via Activity-Feed Flooding after Patch
HackerOne report #3140313 by pwnie on 2025-05-12, assigned to @greg:
Report
Summary
The recent patch to ProcessCommitWorker verifies that the current user (the authenticated pusher) is allowed to close an issue. However, it still writes the commit author into issue.closed_by. Because Git author data can be forged, an attacker can:
- Grant the victim the necessary permission by adding them to the attacker-controlled project (e.g., Developer role).
- Forge commits that reference “Close # x” while spoofing the victim’s name + email in the author field.
The permission check passes—because the victim does have close rights in that project—so the issue really closes, but the event is logged as if the victim performed the action. The attacker can repeat this indefinitely, creating hundreds or thousands of “Closed issue” entries under the victim’s public profile and contribution graph.
Steps to Reproduce
-
Set-up
Attacker creates a public project A.
Attacker invites Victim as Developer (or higher), conferring issue-close rights. -
Seed Issues
Attacker opens many trivial issues in project A (#1 … #N). -
Forge & Push Commits
git clone ATTACKER_REPO_URL cd ATTACKER_REPO for i in $(seq 1 N); do echo $i > junk$i git add junk$i GIT_AUTHOR_NAME="Victim" \ GIT_AUTHOR_EMAIL="victim@example.com" \ git commit -m "Close #$i" done git push origin main -
Observe
- All issues
#1 … #Nclose successfully. - Victim’s profile activity feed shows N “closed issue” events, attributed to Victim, even though Victim never interacted.
- All issues
Impact
| Aspect | Result |
|---|---|
| Integrity | Falsifies historical record of who performed project actions. |
| Reputation | Makes Victim appear responsible for mass-closing spammy issues, damaging trust. |
| Denial of Visibility | Floods Victim’s activity graph, burying genuine contributions. |
| Scalability | Limited only by attacker’s willingness to create issues; cost is negligible. |
Because the closure is legitimate from GitLab’s perspective, victims cannot delete these entries without removing themselves from the project—something they may overlook, and which attackers can re-initiate at any time.
Root Cause
ProcessCommitWorker:
- Confirms current_user (the pusher) has
can?(:update_issue, issue). - Executes
issue.closeand setsclosed_by = commit.author.
Provided the targeted victim has project membership with the requisite permission, step 1 passes. Step 2 then records the spoofed author.
Suggested Remediation
- Attribute to the pusher, not the commit author, when auto-closing.
- If author and pusher differ, mark the event system-generated (“Closed by commit pushed by current_user”).
- Optionally, notify the impersonated user on first occurrence so they can leave the project or report abuse.
- Rate-limit auto-close events per user per project to curb flooding.
Severity
High (Integrity + Reputation Abuse)
The vulnerability enables large-scale, permanent manipulation of public user-history without any compromise of their credentials.
Impact
Because the closure is legitimate from GitLab’s perspective, victims cannot delete these entries without removing themselves from the project—something they may overlook, and which attackers can re-initiate at any time.
How To Reproduce
Please add reproducibility information to this section: