Someone left the master key under the doormat, and the door opens onto your entire software factory
CVE-2026-19478 is a CWE-94 Code Injection flaw in the GraphQL layer of GitLab CE/EE. An unauthenticated, remote attacker can craft a malicious GraphQL directive to modify or delete public projects and user data without any login. Affected versions span a massive range: every release from 18.2 through 18.11.10, 19.0 through 19.0.7, 19.1 through 19.1.5, and 19.2 through 19.2.3. GitLab patched it on 2026-08-17 in versions 18.11.11, 19.0.8, 19.1.6, and 19.2.4.
GitLab rated this CRITICAL at 9.4 and that label is justified. The CVSS vector (AV:N/AC:L/PR:N/UI:N) confirms the worst combination: no authentication, no user interaction, low complexity, and network-reachable. The CWE-94 classification means this is not merely a data-tampering bug—it is *code injection*, which on a CI/CD platform like GitLab means pipeline poisoning and supply-chain compromise are in scope. The only mild relief is the advisory’s qualifier “under certain conditions” and the stated scope being “public projects,” but on internet-facing GitLab instances, public projects are the default attack surface.
5 steps from start to impact.
Identify internet-facing GitLab instance
/help or /api/v4/version endpoints, which are often unauthenticated.- Internet-facing GitLab CE/EE instance in vulnerable version range
- Organizations behind VPN or zero-trust gateways are not reachable
- GitLab.com and GitLab Dedicated are already patched by vendor
http.title:GitLab or X-GitLab-Meta header. Version enumeration via API.Craft malicious GraphQL directive payload
/api/graphql endpoint. The directive bypasses normal authorization checks and allows injection of arbitrary operations.- GraphQL API endpoint accessible (default on all GitLab instances)
- No WAF blocking malformed GraphQL queries
- WAF rules inspecting GraphQL payloads may block unusual directives
- Rate limiting on the GraphQL endpoint may slow exploitation
Modify public project source code or CI configuration
.gitlab-ci.yml, Dockerfile, or dependency manifests. This is the supply-chain pivot: the next CI/CD pipeline run executes attacker-controlled code in the build environment, which may have access to secrets, deploy tokens, and downstream artifact registries.- Target has at least one public project with CI/CD enabled
- Pipeline runs triggered on commit or merge
- Organizations using protected branches with required approvals add a review gate
- Projects with no CI/CD pipelines limit blast radius to source code integrity
Delete projects or exfiltrate user data
- GraphQL schema exposes destructive mutations reachable via the injection
- Regular backups mitigate deletion impact but not confidentiality loss
- Audit logging may trigger alerts on bulk deletions
Pivot via stolen CI/CD secrets
- CI/CD variables contain sensitive credentials
- Build environment has network access to production systems
- Organizations using ephemeral runners with no persistent secrets reduce exposure
- Vault-based dynamic secret injection limits window of credential validity
The supporting signals.
| In-the-Wild Exploitation | Not reported. GitLab did not disclose active exploitation at patch time. Not listed on CISA KEV as of 2026-08-18. |
|---|---|
| Proof-of-Concept | No public PoC as of 2026-08-18. GitLab’s 90-day disclosure policy means technical details will likely emerge around November 2026. Community PoC repos (e.g., SecureWithUmer/CVE-2026-PoCs) do not yet list this CVE. |
| EPSS Score | Not yet scored — CVE disclosed 2026-08-17, EPSS typically populates within 7–14 days. Given the unauth/network/low-complexity vector, expect a high-percentile score once populated. |
| KEV Status | Not listed. No CISA KEV entry as of 2026-08-18. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H — Unauthenticated network attack, low complexity, high integrity and availability impact. Confidentiality is Low because the injection targets public data modification/deletion rather than private data exfiltration. |
| Affected Versions | GitLab CE/EE 18.2 through 18.11.10, 19.0.0–19.0.7, 19.1.0–19.1.5, 19.2.0–19.2.3 |
| Fixed Versions | 18.11.11, 19.0.8, 19.1.6, 19.2.4 (released 2026-08-17) |
| Scanning / Exposure | Shodan and Censys historically index 50,000–80,000+ internet-facing GitLab instances globally. GitLab.com SaaS and GitLab Dedicated are already patched by the vendor; only self-managed installs are at risk. |
| Disclosure Date | 2026-08-17 (GitLab critical patch release) |
| Reporter | Not disclosed. GitLab’s advisory does not attribute the finding to a named researcher. |
noisgate verdict.
The single most decisive factor is the supply-chain role multiplier: GitLab is canonically a CI/CD platform and source code repository, and code injection (CWE-94) into public projects enables pipeline poisoning that can cascade to production deployments, artifact registries, and downstream consumers. Unauthenticated network access with no user interaction on a platform with tens of thousands of internet-facing instances leaves no room to downgrade below CRITICAL.
Why this verdict
- Unauth + network + low complexity = maximum reachability. The CVSS vector PR:N/UI:N/AC:L means any scanner or script kiddie can fire this at exposed instances. No credential theft or phishing chain is needed to reach the vulnerable endpoint.
- CWE-94 Code Injection on a CI/CD platform is supply-chain-grade severity. This is not a simple XSS or information leak. Code injection into repositories means
.gitlab-ci.ymlpoisoning, which executes attacker code in build pipelines with access to deploy secrets. - Role multiplier: GitLab is a canonical CI/CD + source code platform. 100% of GitLab installations serve this high-value role by definition. The blast radius of a successful attack is *supply-chain-scale*: compromised builds propagate to production, container registries, and consumers. Per the HARD RULE, the verdict floor for canonical high-value-role components with supply-chain-scale outcomes is CRITICAL.
- Large internet-facing population. Tens of thousands of self-managed GitLab instances are indexed by Shodan/Censys. Unlike niche appliances, GitLab is commonly exposed to the internet for developer access, especially in organizations without VPN mandates.
- Vendor agrees at CRITICAL 9.4. GitLab’s own severity assessment and the decision to issue a *critical* out-of-band patch release confirms the urgency. The 0.2-point reduction to 9.2 reflects the “under certain conditions” qualifier and limitation to public projects.
Why not higher?
The reassessed score of 9.2 is already CRITICAL. A 10.0 would require confirmed wormable RCE with no conditions; the advisory’s “under certain conditions” language and the scope limitation to public projects prevent a perfect score. Confidentiality impact is rated Low in the vendor’s own vector, indicating private repositories may not be directly reachable.
Why not lower?
Downgrading below CRITICAL is blocked by the role-multiplier floor: GitLab is *definitionally* a CI/CD and source code management platform, and code injection on such a platform has supply-chain-scale blast radius. The unauthenticated attack vector with no user interaction on a widely internet-exposed product means friction is minimal. The absence of a public PoC is a *temporal* factor that will change within weeks, not a structural mitigation.
What to do — in priority order.
- Block unauthenticated access to
/api/graphqlat the reverse proxy or WAF — If your GitLab instance must remain internet-facing, restrict the GraphQL endpoint to authenticated sessions only at the nginx/HAProxy/WAF layer. This neutralizes the unauth attack vector. Deploy within 3 days per the noisgate mitigation SLA for CRITICAL findings. - Place self-managed GitLab behind VPN or zero-trust gateway — Removing GitLab from direct internet exposure eliminates the network attack vector entirely. This is the single most effective compensating control. If not already in place, prioritize this within the 3-day mitigation window.
- Enable GitLab audit logging and alert on project mutations — Configure GitLab’s audit event streaming to your SIEM. Alert on project deletion events, unexpected repository pushes to public projects, and bulk GraphQL mutations. This provides detection coverage while patching is underway.
- Review and restrict public project visibility — Audit your GitLab instance for projects set to ‘Public’ visibility. Convert any that do not need to be public to ‘Internal’ or ‘Private.’ This shrinks the attack surface since the vulnerability targets public projects.
- Rotate CI/CD secrets after patching — Once the patch is applied, rotate all CI/CD variables, deploy tokens, and runner registration tokens. If the instance was exposed pre-patch, assume secrets may be compromised.
- IP-based rate limiting alone — the attack may require only a single crafted GraphQL request, so rate limiting does not prevent exploitation.
- GitLab’s built-in 2FA/MFA — the vulnerability is unauthenticated, so MFA on user accounts has no effect on this attack path.
- Network segmentation between GitLab and internal services — while this limits lateral movement, it does not prevent the initial code injection or project deletion on the GitLab instance itself.
Crowdsourced verification payload.
Run this script on your GitLab server (or any host with network access to the GitLab API) as any user. Example: bash check_cve_2026_19478.sh https://gitlab.example.com. No special privileges required—it only queries the version API.
#!/usr/bin/env bash\n# check_cve_2026_19478.sh\n# Checks whether a GitLab instance is vulnerable to CVE-2026-19478\n# Usage: bash check_cve_2026_19478.sh <GITLAB_URL>\n# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN\n\nset -euo pipefail\n\nif [ $# -lt 1 ]; then\n echo \"Usage: $0 <GITLAB_URL>\"\n echo \"Example: $0 https://gitlab.example.com\"\n exit 2\nfi\n\nGITLAB_URL=\"${1%/}\"\n\n# Try to get version from API\nVERSION_JSON=$(curl -sk --max-time 10 \"${GITLAB_URL}/api/v4/version\" 2>/dev/null || true)\n\nif [ -z \"$VERSION_JSON\" ]; then\n # Fallback: try the help page\n VERSION_HTML=$(curl -sk --max-time 10 \"${GITLAB_URL}/help\" 2>/dev/null || true)\n VERSION=$(echo \"$VERSION_HTML\" | grep -oP '\\d+\\.\\d+\\.\\d+(-\\w+)?' | head -1)\nelse\n VERSION=$(echo \"$VERSION_JSON\" | grep -oP '\"version\"\\s*:\\s*\"\\K[^\"]+' || true)\nfi\n\nif [ -z \"$VERSION\" ]; then\n echo \"UNKNOWN - Could not determine GitLab version at ${GITLAB_URL}\"\n echo \"The API may require authentication. Try: curl -sk ${GITLAB_URL}/api/v4/version --header 'PRIVATE-TOKEN: <token>'\"\n exit 2\nfi\n\necho \"Detected GitLab version: $VERSION\"\n\n# Parse version components\nMAJOR=$(echo \"$VERSION\" | cut -d. -f1)\nMINOR=$(echo \"$VERSION\" | cut -d. -f2)\nPATCH=$(echo \"$VERSION\" | cut -d. -f3 | cut -d- -f1)\n\n# Version comparison\n# Vulnerable: 18.2.0 - 18.11.10, 19.0.0 - 19.0.7, 19.1.0 - 19.1.5, 19.2.0 - 19.2.3\n# Fixed: 18.11.11, 19.0.8, 19.1.6, 19.2.4+\n\nVULNERABLE=0\n\nif [ \"$MAJOR\" -eq 18 ]; then\n if [ \"$MINOR\" -ge 2 ] && [ \"$MINOR\" -le 10 ]; then\n VULNERABLE=1\n elif [ \"$MINOR\" -eq 11 ] && [ \"$PATCH\" -le 10 ]; then\n VULNERABLE=1\n fi\nelif [ \"$MAJOR\" -eq 19 ]; then\n if [ \"$MINOR\" -eq 0 ] && [ \"$PATCH\" -le 7 ]; then\n VULNERABLE=1\n elif [ \"$MINOR\" -eq 1 ] && [ \"$PATCH\" -le 5 ]; then\n VULNERABLE=1\n elif [ \"$MINOR\" -eq 2 ] && [ \"$PATCH\" -le 3 ]; then\n VULNERABLE=1\n fi\nfi\n\nif [ \"$VULNERABLE\" -eq 1 ]; then\n echo \"VULNERABLE - GitLab $VERSION is affected by CVE-2026-19478\"\n echo \"Upgrade to 18.11.11, 19.0.8, 19.1.6, or 19.2.4 immediately.\"\n exit 1\nelse\n echo \"PATCHED - GitLab $VERSION is not affected by CVE-2026-19478\"\n exit 0\nfiIf you remember one thing.
Sources
- GitLab Critical Patch Release 19.2.4, 19.1.6, 19.0.8, 18.11.11
- GitLab Forum — Critical Patch Announcement
- IT Boltwise — GitLab GraphQL Vulnerability Coverage (German)
- CyberSecurityNews — GitLab Patches Security Vulnerabilities
- FIRST EPSS — Exploit Prediction Scoring System
- SecureWithUmer CVE-2026 PoC Collection
- CCB Belgium — GitLab CE/EE Advisory
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.