Exploitation of Web-Facing GitLab and Langflow
An adversary is exploiting GitLab unauthenticated file reads or Langflow authenticated RCE to access repository secrets or execute code on the server host, starting from public-facing assets.
Based on research by Rapid7 2026-09-28 9 steps · 3 queries T1190
Brief
Why now
Rapid7's latest Metasploit Wrap Up: Belgian Waffles, Chocolates, and…Modules-Frites? (https://www.rapid7.com/blog/post/pt-metasploit-wrap-up-belgian-waffles-chocolates-and-modules-frites) includes new modules for GitLab and Langflow. These modules simplify exploitation for attackers looking to read repository secrets or execute code on AI service hosts. While these vulnerabilities are critical, catching them in the wild is difficult because the exploit traffic often mirrors legitimate administrative use.
How the hunt flows
The hunt starts by querying vulnerability management data. It identifies every host in the estate flagged with CVE-2026-85706 or CVE-2026-18729. This step focuses the behavioral search on the most at-risk systems and prevents the hunt from processing logs for patched or non-vulnerable assets.
For GitLab assets, the hunt examines HTTP logs for repository API requests. It calculates the prevalence of requests to specific commit and file paths. High-frequency or rare source IPs requesting these paths suggest a Metasploit module harvesting repository contents rather than a developer performing standard work.
Simultaneously, the hunt monitors Langflow service processes. It looks for common shells like bash or powershell.exe spawned as child processes of the Langflow service. Since Langflow does not typically launch interactive shells for its internal operations, these events indicate successful code execution.
An automated agent then correlates the vulnerability status with any observed network or process anomalies. This step filters out standard administrative activity and provides a per-host verdict. If the agent finds high-confidence evidence of an exploit, it routes the host for immediate isolation and credential revocation.
What the hunt cannot see
If the organization does not decrypt HTTPS traffic at the proxy or log it at the application level, the GitLab API request patterns remain invisible to the HTTP surface. The hunt also faces a challenge with Langflow if a sophisticated attacker executes Python code entirely in-memory within the service process. If no child process spawns, the process-based query will not trigger.
In this series
Steps
-
Identify vulnerable web assets
Query · scopingLocate hosts with reported vulnerabilities corresponding to the Metasploit module release to prioritize the behavioral search.
reads hb_vulnerability_findingsqlSELECT device_uid, resource_uid, cve_uid, severity, title FROM hb_vulnerability_finding WHERE instr(',' || '{{vulnerable_cves}}' || ',', ',' || cve_uid || ',') > 0What a hit looks like. A list of device identifiers or resources flagged with the target CVEs. Silence means the vulnerability scanner has not identified these risks in the estate.
-
GitLab repository API request prevalence
Query · baselineIdentify rare or unauthorized access to repository commits and files APIs that suggest an automated gather module is reading files.
reads hb_http_activitysqlSELECT src_endpoint_ip, url_path, device_hostname, COUNT(*) as request_count, MIN(time) as first_seen FROM hb_http_activity WHERE (LOWER(url_path) LIKE '%/api/v4/projects/%/repository/commits%' OR LOWER(url_path) LIKE '%/api/v4/projects/%/repository/files%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY src_endpoint_ip, url_path, device_hostnameWhat a hit looks like. Anomalous requests to specific API paths. Rare combinations of URL paths and source IPs indicate potential exploit attempts.
-
Langflow anomalous child processes
Query · detection candidateDetect authenticated RCE in Langflow by identifying shells or interpreters spawned by the Langflow service process.
reads hb_process_activitysqlSELECT device_hostname, process_name, process_cmd_line, parent_process_name, parent_process_cmd_line, user_name, time FROM hb_process_activity WHERE LOWER(parent_process_cmd_line) LIKE '%langflow%' AND instr(',' || '{{target_shells}}' || ',', ',' || LOWER(process_name) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Shell instances where the parent command line identifies Langflow, indicating code execution.
-
Triage exploitation signals
Agent triageSynthesize the presence of vulnerable applications with observed HTTP and process anomalies to settle on a verdict.
-
Route on triage verdict
DecisionDetermine whether to contain a host, task an analyst, or close the hunt based on the agent findings.
-
Isolate host and revoke credentials
Response actionImmediately contain the breach to prevent further data exfiltration or lateral movement.
-
Manual forensic validation
Analyst taskReview the telemetry to confirm the scope of the compromise and identify any data exfiltrated.
-
Hunt closure and reporting
Analyst taskDocument the findings and ensure vulnerable systems are scheduled for patching.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| GitLab Unauthenticated Arbitrary File Read T1190 |
Yes | identify-vulnerable-assets, gitlab-api-requests |
| Langflow AI Authenticated RCE T1190 |
Yes | identify-vulnerable-assets, langflow-suspicious-children |
| IPv6 DNS Takeover Coercion T1190 |
Out of scope | Belongs to another part of the 'Metasploit Wrap Up: Belgian Waffles, Chocolates, and…Modules-Frites?' series. |
| Anomalous RDP Interaction T1021.001 |
Out of scope | Belongs to another part of the 'Metasploit Wrap Up: Belgian Waffles, Chocolates, and…Modules-Frites?' series. |
| Kate Plugin Persistence T1190 |
Out of scope | Belongs to another part of the 'Metasploit Wrap Up: Belgian Waffles, Chocolates, and…Modules-Frites?' series. |
Blind spots
- Needs TLS decryption at the proxy or application-level logging. If GitLab traffic is not decrypted at a monitoring point, hb_http_activity will not show the URL path, missing the exploit attempts. It would answer whether file read attempts occurred over encrypted HTTPS channels.
- Needs hb_process_activity and script telemetry. Sophisticated RCE may execute code without spawning a separate shell; if no child process is created, the process-based query will not trigger. It would answer whether Python code executed entirely within the Langflow interpreter process.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
lookback_days | number | 14 | Days of history to examine. |
scope_hosts | list[host] | — | Specific hostnames to narrow the behavioral search; leave empty for fleet-wide. |
target_shells | list[string] | sh, bash, zsh, cmd.exe, powershell.exe, pwsh.exe | Executables commonly used as shells for RCE persistence or command execution. |
vulnerable_cves | list[string] | CVE-2026-85706, CVE-2026-18729 | Targeted CVE identifiers for GitLab and Langflow. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Web server / proxy logs | siem | network |
Source
---
analysis: A simple detection rule for GitLab API paths would trigger on regular administrative
activity; this hunt uses prevalence to isolate rare access patterns and correlates
it with known vulnerable assets and secondary process-level indicators for Langflow.
blind_spots:
- id: gitlab-https-decryption
question: whether file read attempts occurred over encrypted HTTPS channels
requires: TLS decryption at the proxy or application-level logging
risk: If GitLab traffic is not decrypted at a monitoring point, hb_http_activity
will not show the URL path, missing the exploit attempts.
stage: gitlab-unauthenticated-file-read
- id: in-memory-python-execution
question: whether Python code executed entirely within the Langflow interpreter
process
requires: hb_process_activity and script telemetry
risk: Sophisticated RCE may execute code without spawning a separate shell; if no
child process is created, the process-based query will not trigger.
stage: langflow-authenticated-rce
coverage:
- stage: gitlab-unauthenticated-file-read
status: covered
steps:
- identify-vulnerable-assets
- gitlab-api-requests
- stage: langflow-authenticated-rce
status: covered
steps:
- identify-vulnerable-assets
- langflow-suspicious-children
- reason: "Belongs to another part of the 'Metasploit Wrap Up: Belgian Waffles, Chocolates,\
\ and\u2026Modules-Frites?' series."
stage: ipv6-dns-takeover-coercion
status: out_of_scope
- reason: "Belongs to another part of the 'Metasploit Wrap Up: Belgian Waffles, Chocolates,\
\ and\u2026Modules-Frites?' series."
stage: rdp-anomalous-interaction
status: out_of_scope
- reason: "Belongs to another part of the 'Metasploit Wrap Up: Belgian Waffles, Chocolates,\
\ and\u2026Modules-Frites?' series."
stage: kate-plugin-persistence
status: out_of_scope
guardrails:
claims: no_unsupported
evidence: citation_required
missing_data: not_benign
telemetry: untrusted
hunt:
applicability: campaign-specific
handoff: keep-as-periodic-hunt
justification: Metasploit modules for unauthenticated file reads and authenticated
RCE lower the barrier for attackers to gain initial access to repository secrets
or server environments; a negative result over vulnerable assets confirms no immediate
active compromise.
methodology: model-assisted
trigger: intel-report
hypothesis: An adversary is exploiting GitLab unauthenticated file reads or Langflow
authenticated RCE to access repository secrets or execute code on the server host,
starting from public-facing assets.
labels:
- hunt
- attack.t1190
name: Exploitation of Web-Facing GitLab and Langflow
parameters:
lookback_days:
default: '14'
description: Days of history to examine.
from:
kind: manual
observed: '2026-09-25'
ref: default
type: number
scope_hosts:
default: []
description: Specific hostnames to narrow the behavioral search; leave empty for
fleet-wide.
from:
kind: manual
observed: '2026-09-25'
ref: analyst-defined
type: list[host]
target_shells:
default:
- sh
- bash
- zsh
- cmd.exe
- powershell.exe
- pwsh.exe
description: Executables commonly used as shells for RCE persistence or command
execution.
from:
kind: manual
observed: '2026-09-25'
ref: standard-tradecraft
type: list[string]
vulnerable_cves:
default:
- CVE-2026-85706
- CVE-2026-18729
description: Targeted CVE identifiers for GitLab and Langflow.
from:
kind: article
observed: '2026-09-25'
ref: Rapid7 Metasploit Wrap Up
type: list[string]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://www.rapid7.com/blog/post/pt-metasploit-wrap-up-belgian-waffles-chocolates-and-modules-frites
gates:
- dry-run
- lint
model: hb_google/gemini-3-flash-preview
rationale: Start with servers identified in hb_vulnerability_finding with the target
CVEs. Prioritize internet-facing GitLab instances and Langflow environments used
for development or production AI workflows.
references:
- name: "Metasploit Wrap Up: Belgian Waffles, Chocolates, and\u2026Modules-Frites?"
url: https://www.rapid7.com/blog/post/pt-metasploit-wrap-up-belgian-waffles-chocolates-and-modules-frites
related:
- hunt: ipv6-dns-takeover-coercion
reason: Lateral movement via DHCPv6 and DNS coercion is a distinct technique requiring
different network and identity telemetry.
relation: out-of-scope-alternative
scenario:
stages:
- name: GitLab Unauthenticated Arbitrary File Read
observables:
- CVE-2026-85706
- HTTP requests to GitLab repository commits APIs
- HTTP requests to GitLab repository files APIs
- 'Module: gather/gitlab_file_read_cve_2026_85706'
- Affected GitLab versions 18.7 up to 19.3.2
slug: gitlab-unauthenticated-file-read
tactic: initial-access
techniques:
- T1190
- name: Langflow AI Authenticated RCE
observables:
- CVE-2026-18729
- Authenticated HTTP requests to Langflow custom components
- Arbitrary Python code execution via Langflow process
- 'Module: multi/http/langflow_auth_rce_cve_2026_18729'
- Langflow versions 1.11.1 and below
slug: langflow-authenticated-rce
tactic: execution
techniques:
- T1190
- name: IPv6 DNS Takeover Coercion
observables:
- CVE-2026-20929
- Rogue DHCPv6 server activity on UDP port 547
- Rogue IPv6 Router Advertisements (RA)
- Kerberos authentication relay attempts
- 'Module: spoof/dhcp/dhcpv6_dns_takeover'
- 'Module: spoof/ipv6/ipv6_ra_dns_takeover'
slug: ipv6-dns-takeover-coercion
tactic: credential-access
techniques:
- T1190
- name: Anomalous RDP Interaction
observables:
- Unexpected size RDP packets and responses
- Anomalous Remote Interactive logons
- RDP connections to internal assets on port 3389
slug: rdp-anomalous-interaction
tactic: lateral-movement
techniques:
- T1021.001
- name: Kate Plugin Persistence
observables:
- Writes to Kate editor plugin directories
- New plugin configuration files for Kate editor
- 'Module: multi/persistence/kate_plugin'
slug: kate-plugin-persistence
tactic: persistence
techniques:
- T1190
summary: Recent Metasploit updates introduced exploitation modules for unauthenticated
file read in GitLab (CVE-2026-85706) and authenticated RCE in Langflow AI (CVE-2026-18729).
The release also features native IPv6 DNS takeover modules for Kerberos relay
attacks and a new persistence mechanism targeting the Kate text editor.
series:
index: 1
slug: metasploit-wrap-up-belgian-waffles-chocolates-and-modules-frites
title: "Metasploit Wrap Up: Belgian Waffles, Chocolates, and\u2026Modules-Frites?"
total: 2
severity: high
targets:
analyst:
name: Tier-2 analyst
role: analyst
endpoint:
category: endpoint
name: Endpoint telemetry (hb_ surfaces)
telemetry:
- endpoint
hunter:
agent: true
name: Hunt agent
web:
category: siem
name: Web server / proxy logs
telemetry:
- network
tlp: clear
type: investigation
---
# Exploitation of Web-Facing GitLab and Langflow
This hunt targets two critical web vulnerabilities recently integrated into Metasploit: an unauthenticated local file read in GitLab (CVE-2026-85706) and an authenticated remote code execution in Langflow (CVE-2026-18729). The hunt begins by identifying vulnerable assets using inventory and vulnerability data, then checks for signs of active exploitation in parallel: it looks for rare GitLab API access patterns that suggest automated file harvesting, and detects anomalous shell processes originating from the Langflow AI service. An agent then triages the evidence per host to decide between containment or manual forensic review.
## identify-vulnerable-assets
<!-- Identify vulnerable web assets -->
Locate hosts with reported vulnerabilities corresponding to the Metasploit module release to prioritize the behavioral search.
```sqlite target=endpoint role=scoping params=(vulnerable_cves=vulnerable_cves)
~~~yaml
expected: A list of device identifiers or resources flagged with the target CVEs.
Silence means the vulnerability scanner has not identified these risks in the estate.
reads:
- device_uid
- resource_uid
- cve_uid
- severity
- title
silence: not_evidence_of_absence
source: hb_vulnerability_finding
verified: dry-run
verified_at: '2026-09-28'
~~~
SELECT device_uid, resource_uid, cve_uid, severity, title FROM hb_vulnerability_finding WHERE instr(',' || '{{vulnerable_cves}}' || ',', ',' || cve_uid || ',') > 0
```
## exploitation-check
<!-- Check for exploitation activity -->
parallel:
- → gitlab-api-requests
- → langflow-suspicious-children
join: → triage-verdict
## gitlab-api-requests
<!-- GitLab repository API request prevalence -->
Identify rare or unauthorized access to repository commits and files APIs that suggest an automated gather module is reading files.
```sqlite target=web role=baseline params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: Anomalous requests to specific API paths. Rare combinations of URL paths
and source IPs indicate potential exploit attempts.
prevalence:
by: device_hostname
key:
- url_path
rare_below: 3
reads:
- src_endpoint_ip
- url_path
- device_hostname
- time
silence: not_evidence_of_absence
source: hb_http_activity
verified: dry-run
verified_at: '2026-09-28'
~~~
SELECT src_endpoint_ip, url_path, device_hostname, COUNT(*) as request_count, MIN(time) as first_seen FROM hb_http_activity WHERE (LOWER(url_path) LIKE '%/api/v4/projects/%/repository/commits%' OR LOWER(url_path) LIKE '%/api/v4/projects/%/repository/files%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY src_endpoint_ip, url_path, device_hostname
```
## langflow-suspicious-children
<!-- Langflow anomalous child processes -->
Detect authenticated RCE in Langflow by identifying shells or interpreters spawned by the Langflow service process.
```sqlite target=endpoint role=detection-candidate params=(scope_hosts=scope_hosts, lookback_days=lookback_days, target_shells=target_shells)
~~~yaml
expected: Shell instances where the parent command line identifies Langflow, indicating
code execution.
reads:
- device_hostname
- process_name
- process_cmd_line
- parent_process_name
- parent_process_cmd_line
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-28'
~~~
SELECT device_hostname, process_name, process_cmd_line, parent_process_name, parent_process_cmd_line, user_name, time FROM hb_process_activity WHERE LOWER(parent_process_cmd_line) LIKE '%langflow%' AND instr(',' || '{{target_shells}}' || ',', ',' || LOWER(process_name) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```
## triage-verdict
<!-- Triage exploitation signals -->
```agent target=hunter
cite: required
context:
- identify-vulnerable-assets
- gitlab-api-requests
- langflow-suspicious-children
max_iterations: 5
objective: Determine if any host shows evidence of active exploit attempts in network
or process telemetry that correlate with identified vulnerabilities.
success_criteria: A verdict for every scoped host citing relevant rows from HTTP or
process queries.
tools:
- endpoint
- web
```
## route-verdict
<!-- Route on triage verdict -->
if~: "The triage verdict is malicious or suspicious for at least one host based on the correlation of vulnerabilities and exploit indicators." (confidence: high, judge=hunter)
then: → contain-host
indeterminate: → analyst-review
unavailable: → analyst-review (blind_spot: gitlab-https-decryption)
else: → close-out
## contain-host
<!-- Isolate host and revoke credentials -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the compromised host via the EDR console and revoke active GitLab or Langflow authentication tokens for any users identified in the triage context.
```
→ analyst-review
## analyst-review
<!-- Manual forensic validation -->
```manual target=analyst
Review full HTTP logs for the identified server to confirm which repository files were accessed. For Langflow, verify if child processes made any external network connections after spawning.
```
→ close-out
## close-out
<!-- Hunt closure and reporting -->
```manual target=analyst
Record the results of the hunt. If you found vulnerable servers without exploit indicators, ensure they are patched immediately. Record any false positives from the API prevalence query for future tuning.
```
→ end
Run it
Take this hunt into your environment.
Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.
Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.