A source-code platform is one of the most sensitive systems an engineering organization runs. It holds proprietary code, CI/CD credentials, deployment keys, and the pipelines that push software to production. So when a vulnerability lets an unauthenticated attacker take over any account on a self-managed GitLab instance with no clicks from the victim, it is about as serious as software flaws get. CVE-2023-7028 was exactly that: an account-takeover bug in GitLab's password-reset flow, scored at the maximum severity and later confirmed exploited in the wild.
Vulnerability identity and severity
CVE-2023-7028 is an improper access control / authentication flaw in GitLab Community and Enterprise Edition. It carries a CVSS 3.x base score of 10.0 (Critical) — network attack vector, low complexity, no privileges, no user interaction, with a changed scope. The core problem: GitLab would deliver a password-reset link to an unverified, attacker-supplied email address, allowing an attacker to reset the password of an account they do not own.
Timeline and impact
- GitLab 16.1.0 — a change to the password-reset feature introduced the ability to submit a secondary email address for reset delivery, which is where the flaw was born.
- January 11, 2024 — GitLab publishes a critical security release fixing the issue across all affected branches.
- May 2024 — CISA adds CVE-2023-7028 to its Known Exploited Vulnerabilities catalog after evidence of active exploitation, underscoring the real-world risk to self-managed instances.
The impact is stark. Any account without two-factor authentication on a vulnerable, internet-reachable instance could be taken over knowing only the target's email address. From a compromised developer account an attacker can read and modify source, plant malicious commits, steal CI/CD secrets, and pivot into downstream production systems — a textbook software-supply-chain entry point.
Root cause: reset delivery to an unverified address
GitLab's password-reset endpoint accepts an email address and mails a reset token to the account owner. The 16.1.0 enhancement allowed users to receive that reset at a secondary email. The bug was in how the endpoint handled the email parameter: an attacker could submit multiple email addresses — the victim's and one they controlled — and the reset link would be delivered to both. This is a parameter-handling flaw (an array of recipients where a single verified recipient was intended), and no ownership check gated the extra address.
The following is a safe, conceptual illustration of the request shape — not a working exploit:
POST /users/password
user[email][]=victim@company.example
user[email][]=attacker@evil.example
Because the token reached the attacker's inbox, they could complete the reset and set a new password on the victim's account. There was no need to intercept mail, guess a token, or interact with the victim in any way — hence "zero-click." The one meaningful mitigating factor: accounts protected by two-factor authentication could have their password reset, but the attacker still could not pass the second factor, so full takeover was blocked for 2FA-enabled users.
Affected versions
The vulnerability was introduced in 16.1.0 and affects the following ranges. Upgrade to the patched release for your branch:
- 16.1 prior to 16.1.6
- 16.2 prior to 16.2.9
- 16.3 prior to 16.3.7
- 16.4 prior to 16.4.5
- 16.5 prior to 16.5.6
- 16.6 prior to 16.6.4
- 16.7 prior to 16.7.2
Detection
- Inspect Rails/production logs for
POST /users/passwordrequests whose parameters contain more than one email address — the signature of an exploitation attempt. - Review recent password resets and audit events for accounts whose reset was delivered to an unfamiliar address, or whose associated email changed unexpectedly.
- Hunt for follow-on activity on any suspected account: new personal access tokens, added SSH keys, changed pipeline variables, or unexpected sign-ins.
- Confirm your version with
gitlab-rake gitlab:env:infoor the admin dashboard; anything in the ranges above is vulnerable.
Remediation and patched versions
- Upgrade immediately to 16.7.2, 16.6.4, 16.5.6, 16.4.5, 16.3.7, 16.2.9, or 16.1.6 as appropriate for your branch.
- Enforce two-factor authentication, especially for administrators and any account with elevated project access. 2FA was the difference between "password reset" and "full takeover."
- Assume compromise if you ran unpatched and internet-exposed. Rotate credentials, review and revoke suspicious personal access tokens and SSH keys, and audit recent repository and pipeline changes.
- Restrict network exposure of self-managed instances where feasible, placing them behind a VPN or identity-aware proxy.
- Verify the fix by confirming the version post-upgrade and that reset requests with multiple recipients are rejected.
How Safeguard helps
CVE-2023-7028 lived in a deployed application, and its danger was a function of exposure, so detection has to reach beyond package inventory into the running surface. Safeguard's DAST engine probes your deployed GitLab and other web-facing services to confirm which instances are actually reachable and which findings are live, so remediation follows real risk rather than a spreadsheet of versions. Safeguard's software composition analysis tracks the platform and component versions across your self-hosted tooling, flagging an instance that falls inside the affected 16.x ranges. The Safeguard CLI brings that same check into automation, so a vulnerable self-hosted service is caught by policy rather than by luck. If you are comparing Safeguard's combined runtime-and-component coverage against point tools, see how it stacks up.
The lesson of CVE-2023-7028 is that identity flows are attack surface, and a source-code platform is the crown jewels. Patch fast, enforce 2FA, and monitor your reset flows. Create a free Safeguard account or read the documentation to get started.