flawopen.com/Incidents/GitLab CVE-2026-85706
A library has a counter where you hand over a slip of paper with a shelf number, and a clerk fetches that item for you. The clerk was supposed to only accept slips pointing at the public shelves — and was supposed to check your library card first. It did neither. Anyone walking in off the street could write "the manager's filing cabinet" on the slip, and the clerk would go get it.
GitLab disclosed a path traversal vulnerability in the repository commits API of GitLab Community Edition and Enterprise Edition. An unauthenticated attacker able to reach the instance over the network could send a single crafted HTTP request and read arbitrary files from the server's filesystem — anything readable by the account the GitLab application runs as.
GitLab rated the issue CVSS 10.0, its maximum score. Public reporting indicates exploitation attempts began within roughly 24 hours of the patch release, and CISA added the CVE to its Known Exploited Vulnerabilities catalog on 11 September 2026, setting a remediation deadline of 14 September 2026 for federal civilian agencies.
The vulnerable surface is the commits endpoint under the v4 REST API:
POST /api/v4/projects/{id}/repository/commits/
The request body carries a file.path value. That value was used to locate a file without being confined to the repository directory, and the endpoint did not require authentication in the affected code path.
Two independent failures had to line up to produce a CVSS 10.0:
The user-supplied path was not verified to resolve inside the intended repository directory. Traversal sequences in file.path walked the resolved location up and out of the repository root and into the wider filesystem.
A traversal bug behind an authenticated endpoint is serious. The same bug reachable with no credentials at all is catastrophic — it converts every internet-exposed instance into a public file server. This is the factor that pushes the score to the maximum.
GitLab's advisory describes the root cause as improper path confinement together with missing authentication enforcement, but has not published code-level detail of the failed check. The illustration below is a generic demonstration of the class of mistake, not a reproduction of GitLab's source.
# The supplied path is joined to the repo # root and opened. Nothing verifies where # it actually resolves to. full = File.join(repo_root, params[:file][:path]) File.read(full) # file.path = "../../../../etc/passwd" # resolves far outside repo_root
# Resolve first, then prove containment
root = File.realpath(repo_root)
full = File.realpath(
File.join(root, params[:file][:path])
)
unless full.start_with?(root + File::SEPARATOR)
raise ArgumentError, "path escapes repository"
end
File.read(full)The load-bearing idea is that you cannot validate a path by inspecting the string. Blocklisting ../ fails against encoded variants, absolute paths, and symlinks. The only durable check is to fully resolve the path — following every .. and every symlink — and then assert that the resolved result is still underneath the directory you intended.
This is the part teams got wrong. An arbitrary file read on a GitLab server does not just expose source code — it exposes the secrets that the server keeps on disk. Depending on configuration, that can include the instance's shell secret file, SSH host keys, deploy tokens, CI/CD variables and database credentials.
Once those have potentially been read, upgrading closes the hole but leaves the attacker holding valid credentials. Any instance that was internet-reachable and unpatched during the exposure window should be treated as having leaked its secrets, and those secrets rotated.
POST requests to the commits endpoint carrying traversal sequences in the body, especially from unauthenticated sources.The interesting thing about this CVE is not that GitLab shipped a path traversal — it is how ordinary the ingredients were. A parameter named path, a join against a base directory, and an endpoint whose authentication requirement was assumed rather than enforced. Each of those individually appears in a very large number of codebases. The lesson is that path handling and authentication should both be checked at the boundary, mechanically, rather than inherited from the assumption that the surrounding framework already did it.
The advisory scopes the issue to self-managed Community and Enterprise Edition instances. GitLab's own hosted platform was addressed by the vendor directly; the urgent action applies to organisations running their own servers.
Not directly — the primitive is an arbitrary file read. In practice that is often enough to reach code execution indirectly, because the files it exposes include credentials and signing secrets that unlock other systems.
The score reflects that it is remotely reachable, needs no privileges, needs no user interaction, is trivial to exploit, and — because the exposed secrets grant control over other components — its impact is judged to extend beyond the vulnerable component itself.