GitLab
CVE-2026-19650
CVE-2026-19650 GitLab GraphQL multiplex GET handling
OVERVIEW
Lab observed
Vendor reported
Vendor-reported fixed versions
18.11.11 / 19.0.8 / 19.1.6 / 19.2.4Only the lab versions above were independently reproduced by CVE Mapping.
LAB OBSERVED
What this lab demonstrates
The lab reproduced a state-changing GET /api/graphql multiplex request as Victim on 19.2.2-ee.0 and observed no corresponding state change in the same general test pattern on 19.2.4-ee.0.
The vulnerable and patched modes used equivalent controlled actions. Application state—not a successful HTTP status alone—is decisive.
VULNERABLE VS PATCHED RESULT
Runtime accepted and the documented state difference was observed.
Runtime accepted and the expected safe state was retained.
Evidence, telemetry, and detection checks are recorded in the manifest.
DETECTION COVERAGE
Detection engineering
- Sigma2 lab-validated analytics; 1 experimental contextual analytic
- Splunk2 lab-validated analytics
- Elastic2 lab-validated analytics
- osquerysupporting host context
Request telemetry provides context, while the strongest analytic requires correlated application-state telemetry. A request alone does not prove exploitation.
Lab queries
Sigma — graphql_get_multiplex_request.yml lab-validated
title: GitLab GraphQL GET Multiplex Request Context
id: 2a18f6f1-2fa4-4a39-a7f0-194780000001
status: experimental
description: >-
Detects the observed GraphQL multiplex GET request shape and introduced
directive indicator. The same shape is present in the patched control and
is therefore contextual rather than a validated standalone detector.
logsource:
category: webserver
product: gitlab
detection:
selection:
method: GET
path: /api/graphql
url|contains|all:
- /api/graphql
- _json%5B%5D%5Bquery%5D
- '%40gl_introduced'
condition: selection
falsepositives:
- Authorized local lab reproduction
- Legitimate GraphQL multiplex GET traffic on patched GitLab versions
level: high
references:
- https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-4-released/
- https://www.cve.org/CVERecord?id=CVE-2026-19650
fields:
- method
- path
- url
note: >-
Raw URL visibility is required for the encoded multiplex and introduced
indicator. The normalized fixture mapping is http.method -> method and
http.path -> path; url remains a collector-specific request-shape field.
cve_mapping:
cve: CVE-2026-19650
validation_status: experimental
vulnerable_dataset: labs/gitlab/CVE-2026-19650/telemetry/vulnerable/events.jsonl
patched_dataset: labs/gitlab/CVE-2026-19650/telemetry/patched/events.jsonl
Sigma — graphql_get_db_write.yml lab-validated
title: GitLab GraphQL GET With Database Write
id: 2a18f6f1-2fa4-4a39-a7f0-194780000002
status: test
description: >-
Detects a GET GraphQL request with a positive database write count. This is
validated against the CVE-2026-19650 normalized vulnerable and patched
fixtures.
logsource:
category: application
product: gitlab
detection:
selection:
method: GET
path: /api/graphql
write:
db_write_count|gt: 0
condition: selection and write
falsepositives:
- Product-specific GraphQL resolvers that legitimately write
- Authorized administrative or integration workflows that use GET-side effects
level: medium
references:
- https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-4-released/
- https://www.cve.org/CVERecord?id=CVE-2026-19650
fields:
- method
- path
- db_write_count
cve_mapping:
cve: CVE-2026-19650
validation_status: lab-validated
vulnerable_dataset: labs/gitlab/CVE-2026-19650/telemetry/vulnerable/events.jsonl
patched_dataset: labs/gitlab/CVE-2026-19650/telemetry/patched/events.jsonl
note: Correlate with used_fields and application state; HTTP 200 is not proof.
Sigma — graphql_get_issue_create_gate.yml lab-validated
title: GitLab GraphQL GET With Issues Create Gate
id: 2a18f6f1-2fa4-4a39-a7f0-194780000003
status: test
description: >-
Detects a GET GraphQL request associated with the issues_create
rate-limiting gate. The gate is a supporting application signal and should
be correlated with database writes and resulting state.
logsource:
category: application
product: gitlab
detection:
selection:
method: GET
path: /api/graphql
gate:
rate_limiting_gates|contains: issues_create
condition: selection and gate
falsepositives:
- Legitimate application behavior or version-specific rate-limit telemetry
- Authorized issue creation workflows with the same gate name
level: medium
references:
- https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-4-released/
- https://www.cve.org/CVERecord?id=CVE-2026-19650
fields:
- method
- path
- rate_limiting_gates
cve_mapping:
cve: CVE-2026-19650
validation_status: lab-validated
vulnerable_dataset: labs/gitlab/CVE-2026-19650/telemetry/vulnerable/events.jsonl
patched_dataset: labs/gitlab/CVE-2026-19650/telemetry/patched/events.jsonl
Splunk — graphql_get_db_write.spl lab-validated
/*
Analytic: GitLab GraphQL GET With Database Write
CVE: CVE-2026-19650
Expected fields: method, path, db_write_count
Normalized mapping: http.method -> method; http.path -> path;
database.db_write_count -> db_write_count
False positives: legitimate GET-side effects or custom GitLab extensions.
Lab fixture result: vulnerable match, patched no match, benign no match.
*/
method="GET" path="/api/graphql" db_write_count > 0
Splunk — graphql_get_issue_create_gate.spl lab-validated
/*
Analytic: GitLab GraphQL GET With Issues Create Gate
CVE: CVE-2026-19650
Expected fields: method, path, rate_limiting_gates
Normalized mapping: http.method -> method; http.path -> path;
gitlab.rate_limiting_gates -> rate_limiting_gates
False positives: legitimate issue workflows or version-specific gate names.
Lab fixture result: vulnerable match, patched no match, benign no match.
*/
method="GET" path="/api/graphql" rate_limiting_gates="*issues_create*"
Elastic — graphql_get_db_write.json lab-validated
{
"name": "GitLab GraphQL GET With Database Write",
"cve": "CVE-2026-19650",
"type": "query",
"language": "kuery",
"query": "http.method: GET and http.path: \"/api/graphql\" and database.db_write_count > 0",
"severity": "medium",
"risk_rationale": "A GET GraphQL request with a positive application database write count is a state-change signal in the lab fixtures.",
"false_positive_note": "Legitimate GET-side effects, custom extensions, or instrumentation may match; correlate with application state and identity.",
"references": [
"https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-4-released/",
"https://www.cve.org/CVERecord?id=CVE-2026-19650"
],
"fixture_discrimination": {
"vulnerable": 1,
"patched": 0,
"benign": 0
}
}
Elastic — graphql_get_issue_create_gate.json lab-validated
{
"name": "GitLab GraphQL GET With Issues Create Gate",
"cve": "CVE-2026-19650",
"type": "query",
"language": "kuery",
"query": "http.method: GET and http.path: \"/api/graphql\" and gitlab.rate_limiting_gates: \"issues_create\"",
"severity": "medium",
"risk_rationale": "The issues_create gate is a supporting application signal that can be correlated with a GET GraphQL state change.",
"false_positive_note": "Legitimate issue workflows and version-specific rate-limit telemetry may produce the same gate.",
"references": [
"https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-4-released/",
"https://www.cve.org/CVERecord?id=CVE-2026-19650"
],
"fixture_discrimination": {
"vulnerable": 1,
"patched": 0,
"benign": 0
}
}
osquery — gitlab_process_inventory.sql supporting
-- Supporting host context; this does not detect the GraphQL behavior.
SELECT name, pid, cmdline, path
FROM processes
WHERE cmdline LIKE '%gitlab%' OR cmdline LIKE '%puma%';
osquery — gitlab_listening_sockets.sql supporting
-- Supporting exposure context; this does not detect the GraphQL behavior.
SELECT local_address, local_port, remote_address, remote_port, state, pid
FROM process_open_sockets
WHERE local_port = 8929 OR remote_port = 8929;
FIXTURE DISCRIMINATION
Lab fixture performance
Validated state-change analytics matched vulnerable activity and did not match patched or benign controls. Contextual analytics are reported separately and are not promoted to vulnerability discriminators.
EVIDENCE & TELEMETRY
Preserved and verifiable
Sanitized evidence and normalized telemetry are tracked by manifest and SHA-256 integrity files.
RISK CONTEXT
Vendor enrichment
CVSS 7.1 · Vendor-reported · observed 2026-08-25
Additional risk feeds are omitted without a verified current lookup.
MITRE ATT&CK
Unassigned
COPYABLE RUNBOOK
Start with the Quickstart.
Disposable, localhost-only runbook commands taken from the lab's QUICKSTART.md. Proof internals stay in the repository — these are the operator workflow commands.
1. Preflight
cd labs/gitlab/CVE-2026-19650
./scripts/lab.sh preflight
./scripts/lab.sh prepare2. Vulnerable flow
./scripts/lab.sh up vulnerable
./scripts/lab.sh wait vulnerable
./scripts/lab.sh init vulnerable./scripts/lab.sh verify vulnerable
./scripts/lab.sh down vulnerable3. Patched flow
./scripts/lab.sh up patched
./scripts/lab.sh wait patched
./scripts/lab.sh init patched./scripts/lab.sh verify patched
./scripts/lab.sh down patched4. Cleanup
./scripts/lab.sh clean vulnerable
./scripts/lab.sh clean patched./scripts/lab.sh status vulnerable
./scripts/lab.sh diagnose vulnerable
WAIT_TIMEOUT_SECONDS=1800 ./scripts/lab.sh wait vulnerable5. Validate repository fixtures
cd ../../..
python3 scripts/validate-lab-manifest.py --all
python3 scripts/validate-detections.py --all
python3 labs/gitlab/CVE-2026-19650/scripts/build-telemetry.py --check
python3 scripts/verify-integrity.py --allLIMITATIONS & SAFETY
Scope stays explicit.
The lab does not claim independent reproduction of every vendor-reported version. It requires authorized defensive use, synthetic identity, and a bounded controlled proof.