← All labs

GitLab

CVE-2026-19650

CVE-2026-19650 GitLab GraphQL multiplex GET handling

REPRODUCED LAB VALIDATED

OVERVIEW

Lab observed

Vulnerable19.2.2-ee.0
Patched19.2.4-ee.0

Vendor reported

Vendor-reported fixed versions

18.11.11 / 19.0.8 / 19.1.6 / 19.2.4

Only 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

VULNERABLE

Runtime accepted and the documented state difference was observed.

PATCHED CONTROL

Runtime accepted and the expected safe state was retained.

CI VALIDATED

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

View on GitHub

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.

View on GitHub

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

View on GitHub

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

View on GitHub

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*"

View on GitHub

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
  }
}

View on GitHub

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
  }
}

View on GitHub

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%';

View on GitHub

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;

View on GitHub

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.

Validated state-change · Vulnerable2 matched
Validated state-change · Patched0 matched
Validated state-change · Benign0 matched
Contextual request · Vulnerable1 matched
Contextual request · Patched1 matched
Contextual request · Benign0 matched

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 prepare
2. 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 vulnerable
3. 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 patched
4. 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 vulnerable
5. 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 --all

LIMITATIONS & 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.