In late 2023, a security vulnerability—CVE-2023-5198—was publicly reported affecting multiple versions of GitLab, one of the most popular platforms for managing private Git repositories. This issue specifically allowed removed project members to still have write access to protected branches, using deploy keys they previously authorized. Here’s an in-depth, easy-to-read breakdown of what happened, why it matters, and how attackers could have exploited this flaw.

16.4.

- Vulnerable Scenario: If a user with write access to protected branches was removed from a project, any deploy keys they had set up remained authorized, still allowing them to push code to branches that should have been protected.

Official advisory:
GitLab Security Release: 16.4.1, 16.3.5, and 16.2.7

Deploy Keys in GitLab

A deploy key is an SSH key you add to a GitLab project, mostly used by servers to run automated scripts. But they can be given write access—and before this fix, the key wasn’t invalidated if the associated user was removed.

Normal Security Flow:

Broken Security Flow (CVE-2023-5198):

Eve is a DevOps engineer on ProjectX.

2. She adds a deploy key with write access to protected branches (main, release/ etc.).

Suppose Eve’s deploy key is already configured for ProjectX. Even after being removed, she can run

# After her account is deleted, using the still-active deploy key
GIT_SSH_COMMAND="ssh -i /path/to/deploy_key" \
git push origin HEAD:refs/heads/main

If main is a protected branch, this should be blocked—but in affected GitLab versions, it still succeeds.

Supply Chain Risk:

CI/CD pipelines dependent on protected branches could be compromised.

Automated Script Example (Python 3 + GitLab API)

import requests

GITLAB_URL = "https://gitlab.example.com";
API_TOKEN = "your_access_token_here"

headers = {"PRIVATE-TOKEN": API_TOKEN}

def list_projects():
    return requests.get(f"{GITLAB_URL}/api/v4/projects", headers=headers).json()

def list_deploy_keys(project_id):
    return requests.get(f"{GITLAB_URL}/api/v4/projects/{project_id}/deploy_keys", headers=headers).json()

for project in list_projects():
    print(f"Project: {project['name']}")
    keys = list_deploy_keys(project['id'])
    for key in keys:
        print(f"  Deploy Key: {key['title']} (Can push: {key['can_push']})")

To 16.4.1 or later

Download latest releases from GitLab upgrade releases.

References

- CVE-2023-5198 on cve.org
- GitLab Security Release (Oct 2023)
- GitLab Documentation: Deploy Keys

Conclusion

CVE-2023-5198 is a serious security bug that shows the importance of full lifecycle management of external access mechanisms like deploy keys. If you run a GitLab server or manage repositories with protected branches, check your version, audit active deploy keys, and upgrade immediately.

Stay safe, and keep your repositories locked down against both former employees and automated attacks!

Timeline

Published on: 09/29/2023 08:15:00 UTC
Last modified on: 10/03/2023 19:47:00 UTC