Visualização de leitura

GitLab Warns of Active Exploitation of Critical GraphQL Flaw

GitLab flaw CVE-2026-19478 is now under active exploitation, allowing unauthenticated attackers to modify or delete public projects.

WatchTowr researchers warn of active exploitation of critical GitLab flaw CVE-2026-19478 (CVSS score of 9.4). This week, GitLab pushed out an emergency patch to address this flaw, which could let an attacker with zero credentials remotely modify or delete public projects and user data.

“GitLab has remediated an issue that under certain conditions could allow an unauthenticated user to remotely modify or delete public projects and user data via a GraphQL directive.” reads the advisory.

GitLab issued an emergency patch on August 17, five days after its regular update. The vulnerability impacts only self-managed installations, users should upgrade to versions  19.2.4, 19.1.6, 19.0.8, and 18.11.11.

There’s a gap worth flagging for anyone still sitting on an older release. The available patches don’t cover the 18.2 through 18.10 branches, even though those versions technically fall inside the affected range. If you’re running anything in that window, staying put isn’t really an option; you’ll need to upgrade to a patched branch entirely rather than waiting for a fix that isn’t coming for your current one.

hiimguardian reported the flaw through the company HackerOne bug bounty program.

Organizations should urgently patch internet-facing GitLab servers. Until they can update, they should restrict unauthenticated access to /api/graphql, disable public repositories where possible, and check logs for requests containing @gl_introduced.

Follow me on Twitter: @securityaffairs and Facebook and Mastodon

Pierluigi Paganini

(SecurityAffairs – hacking, CVE-2026-19478)

GitLab Patches Critical Unauthenticated GraphQL Vulnerability

GitLab patched a critical GraphQL flaw that let unauthenticated attackers remotely modify or delete public projects on self-managed servers.

GitLab pushed out an emergency patch this week to address a critical flaw, tracked as CVE-2026-19478 (CVSS score of 9.4), that could let an attacker with zero credentials remotely modify or delete public projects and user data.

“GitLab has remediated an issue that under certain conditions could allow an unauthenticated user to remotely modify or delete public projects and user data via a GraphQL directive.” reads the advisory.

GitLab issued an emergency patch on August 17, five days after its regular update. The vulnerability impacts only self-managed installations, users should upgrade to versions  19.2.4, 19.1.6, 19.0.8, and 18.11.11.

There’s a gap worth flagging for anyone still sitting on an older release. The available patches don’t cover the 18.2 through 18.10 branches, even though those versions technically fall inside the affected range. If you’re running anything in that window, staying put isn’t really an option; you’ll need to upgrade to a patched branch entirely rather than waiting for a fix that isn’t coming for your current one.

hiimguardian reported the flaw through the company HackerOne bug bounty program.

A second, less severe issue shipped in the same release. CVE-2026-19650 (CVSS score of 7.1), involves a cross-site request forgery weakness in how GitLab’s GraphQL handles multiplex queries, letting an unauthenticated attacker trigger mutations through GET requests due to improper validation. Unlike the critical flaw, this one needs a victim to actually interact with something, so it’s a real risk but a considerably narrower one.

There’s no evidence either bug has been exploited in the wild yet, and no public proof-of-concept code has surfaced as of publication. That’s the good news. The less comforting part is GitLab’s own disclosure policy: full technical details typically go public on the company’s issue tracker 90 days after the patching release, which puts a working understanding of exactly how this bug functions squarely in mid-November, plenty of time for someone motivated enough to reverse-engineer the patch diff themselves before then.

This is not the first serious GitLab issue in recent months. Last month, researchers released working exploit code for another remote-code-execution flaw affecting self-managed servers. Organizations running GitLab on their own infrastructure should therefore treat this patch as a priority, especially given the critical severity and the fact that the vulnerability requires no authentication or user interaction.

Follow me on Twitter: @securityaffairs and Facebook and Mastodon

Pierluigi Paganini

(SecurityAffairs – hacking, GitLab)

GitLab Users Urged to Patch After Research Reveals Critical RCE Chain

Researchers chained two Oj parser bugs to achieve GitLab RCE via Jupyter notebook diffs, affecting authenticated users on unpatched versions.

Depthfirst researchers published a working remote code execution exploit for GitLab on July 24, chaining two memory corruption bugs in Oj, a Ruby JSON parser with a native C implementation, into full command execution inside a GitLab Puma worker.

Any authenticated user who can push to a project and view commit diffs could run it. The researchers pointed out that no admin rights, no CI access, and no victim interaction are needed. GitLab patched the bugs on June 10 but listed the fix under bug fixes, not the security table, so operators triaging the release had no reason to treat it as urgent.

“The system surfaced 18 prioritized vulnerabilities, including 7 memory-safety bugs. Two of them, an out-of-bounds write and a heap-pointer disclosure, had survived in Oj for nearly five years.” reads the report published by Depthfirst. “Oj is a low-level dependency used by GitLab, and we combined the two bugs to achieve remote code execution on a default GitLab installation.”

The bugs entered Oj’s parser on August 8, 2021. They remained there for 1,753 days. The vulnerable notebook path shipped in GitLab starting with version 15.2.0 in July 2022 and wasn’t fixed until June 10, 2026.

The attack path starts with GitLab’s notebook diff renderer, a small in-tree gem called ipynbdiff that converts Jupyter .ipynb files into human-readable diffs. When a user opens a commit diff for a notebook file, GitLab passes the raw repository bytes to Oj::Parser.usual.parse inside the Puma worker process. That parse call is the entry point.

“The investigation ran in reverse: depthfirst found the vulnerable parser below the application, then traced its callers back to a user-controlled product boundary.” continues the report. “A real request follows that chain in the opposite direction, from a GitLab commit diff into native C code.”

Because Oj::Parser.usual returns a process-wide parser singleton shared across threads in the same Puma worker, corrupting it once affects every subsequent parse in that process.

The first bug is an unchecked nesting stack overflow. Oj keeps track of JSON nesting depth in a fixed 1,024-byte array inside the parser object. When an attacker opens more than 1,024 nested arrays, Oj keeps writing one-byte collection selectors past the end of that buffer, into adjacent parser fields. The attacker can’t control each byte precisely, arrays always write 0x01, but they can control how far the sweep goes. With enough levels, that single byte changes buf.head, the parser’s internal buffer-start pointer, shifting it backward by 127 bytes into memory the parser doesn’t own. From there, a forced realloc caches that forged interior pointer, a Ruby Array allocation reclaims it, and the Array’s element contents, constrained to valid Ruby values but still attacker-influenced, overwrite the parser’s p->start callback pointer with a chosen address.

The second bug provides the address. An oversized object key, 65,565 bytes, gets its length truncated from a size_t to a signed 16-bit integer, which wraps to 29. Oj allocates heap memory for the full key and stores a pointer to it, but the truncated length tells the return path to read 29 bytes from the inline buffer instead. Those 29 bytes happen to contain the heap pointer in bytes 6 through 13. GitLab renders that into the diff as part of the cell ID.

“Returned bytes 0 through 5 came from the external view’s alignment padding. Bytes 6 through 13 were the live key pointer. The final 15 returned bytes came from union storage not written by the external view and could contain stale key-entry contents. This was a fixed 29-byte disclosure, not an arbitrary-address read: it exposed bytes already present in that Key entry and never dereferenced an attacker-selected pointer.” states the report. “These offsets came from the tested x86_64 ABI, so the compiler layout was part of the primitive’s boundary.”

With a heap landmark in hand, the attacker probes candidate libc base addresses by writing a self-looping instruction address into p->start and watching which parse hangs. On a fresh two-worker GitLab install, the ASLR search took five to ten minutes. On a mature long-running instance, the projected time is one to two hours.

Once the library base is recovered, the exploit chains the two primitives in a single diffs_stream request. Two lexically ordered notebook files in the same commit carry the stages: the first notebook arms the callback pointer, raises an exception to avoid immediate execution, and lets GitLab continue streaming diffs. The second notebook’s old side triggers p->start in the same Puma worker, which jumps through two libruby gadgets into system() with the attacker’s command in the right register. Commands run as git, the account behind Puma, which puts source code, Rails secrets, service credentials, and any internal service the application can reach within range.

“Successful exploitation executed commands as git, the account running GitLab’s Puma workers. Its effective reach depends on deployment isolation, but it may include repository data, Rails secrets, service credentials, and internal services available to the application.” concludes the report. “This can lead to source-code disclosure, credential theft, repository modification, persistence, or lateral access.”

GitLab CE and EE versions 15.2.0 through 18.10.7, 18.11.0 through 18.11.4, and 19.0.0 through 19.0.1 are affected across all tiers. Releases before 15.2 used a different JSON parser in this path and aren’t vulnerable. Releases from 15.2 through 18.9 are outside GitLab’s security-maintained patch trains and won’t receive backports — those installs need to move to a supported release. For Helm and Operator deployments, the relevant version is the GitLab version inside the Webservice image running Puma, not the chart version. Upgrade to 18.10.8, 18.11.5, or 19.0.2. No configuration-only workaround has been validated by depthfirst or GitLab.

Follow me on Twitter: @securityaffairs and Facebook and Mastodon

Pierluigi Paganini

(SecurityAffairs – hacking, GitLab)

❌