
From MCPJam Inspector RCE to root — CVE-2026-23744, JupyterLab token disclosure, kernel execution, and OPSMCP privilege escalation
This repository is intended for authorized security research, penetration testing, and educational purposes only. Do not use the techniques described here against systems without explicit authorization.
From MCPJam Inspector RCE to root — CVE-2026-23744, JupyterLab token disclosure, kernel execution, and OPSMCP privilege escalation.
This repository documents a complete Linux attack chain, from an exposed MCPJam Inspector instance to root-level access.
The chain chains together weaknesses across developer tooling, local services, credential handling, and application authorization:
MCPJam Inspector
│ CVE-2026-23744
▼
RCE
│
▼
JupyterLab Token
│
▼
Jupyter Kernel
│
▼
User
│
▼
OPSMCP API
│
▼
Hidden Admin Tool
│
▼
Root Credential
│
▼
root
[!WARNING] This repository is intended for authorized security research, penetration testing, and educational purposes only. Target addresses, credentials, tokens, and other environment-specific values throughout this document are redacted or replaced with lab placeholders.
Initial reconnaissance focuses on identifying externally exposed services.
nmap -sC -sV -oN nmap_initial.txt TARGET
A complete TCP scan can then be performed:
nmap -p- --min-rate 5000 -oN nmap_full.txt TARGET
Relevant external services:
| Port | Service | Role |
|---|---|---|
| 22 | SSH | Remote administration |
| 6274 | MCPJam Inspector | Initial attack surface |
Services bound only to localhost:
| Port | Service | Privilege |
|---|---|---|
| 8888 | JupyterLab | User |
| 5000 | OPSMCP | root |
The externally accessible MCPJam Inspector on port 6274 becomes the initial entry point.
The exposed MCPJam Inspector instance is affected by CVE-2026-23744.
MCPJam Inspector is primarily intended as a development and testing interface for MCP servers. The vulnerability becomes particularly dangerous when this interface is exposed to an untrusted network — a vulnerable configuration flow allows attacker-controlled data to reach a command-execution path.
Remote Request
│
▼
MCP Server Configuration
│
▼
Command Execution
│
▼
Initial Shell
The vulnerability affects MCPJam Inspector versions up to and including 1.4.2. For authorized testing, a public proof of concept can be used to validate the vulnerability against the target environment.
After successful exploitation, confirm the execution context:
id
whoami
hostname
Once the initial foothold is obtained, local services become visible.
ss -tlnp
ps aux | grep -E 'jupyter|python|node'
Network
│
▼
MCPJam Inspector
:6274
│
▼
Initial RCE
│
┌─────────┴─────────┐
▼ ▼
JupyterLab OPSMCP
:8888/local :5000/local
│ │
▼ ▼
User root
The privilege difference between the two internal applications is particularly interesting.
The JupyterLab process was started with its authentication token directly on the command line:
--ServerApp.token=<JUPYTER_TOKEN>
The command line can be inspected via:
ps aux | grep jupyter
# or
cat /proc/<PID>/cmdline
This demonstrates a common secret-management problem:
Secret → Command-line argument → Process metadata → Local credential disclosure
The recovered token provides access to the local Jupyter API.
Jupyter exposes a REST API for managing kernels. After authenticating with the recovered token, a kernel can be created via:
POST /api/kernels
The response contains a kernel UUID. Jupyter kernels communicate through WebSockets:
/api/kernels/<KERNEL_ID>/channels
The Jupyter messaging protocol uses an execute_request message to run Python code:
{
"header": { "msg_type": "execute_request" },
"content": { "code": "<AUTHORIZED_LAB_CODE>" }
}
This establishes Python execution under the identity of the Jupyter service — in this environment, the kernel executes as User.
MCPJam RCE → JupyterLab → User
With a user shell available, the next step is examining locally installed applications. The OPSMCP application is located under:
/opt/opsmcp/
Reviewing the source code reveals an embedded API credential:
VALID_API_KEY = "<REDACTED_OPSMCP_API_KEY>"
The application also maintains two tool collections:
Visible tools
ops.system_statusops.list_servicesops.check_diskops.view_logsHidden tools
ops._admin_dumpops._debug_modeThe administrative functions are particularly interesting because they are not returned through normal tool enumeration.
Not documented does not mean not accessible.
The backend still registers the hidden tools and accepts their names through the generic tool-execution mechanism.
The application authenticates requests using an API key:
X-API-Key: <OPSMCP_API_KEY>
Once authenticated, the tool-execution endpoint only checks whether the requested function exists — not whether the caller is permitted to run it.
What happens:
API Key → Authenticated → Tool exists? → Execute
What should happen:
API Key → Authenticated → Permission check → Allowed → Execute
└ Denied → 403
The hidden administrative function can access sensitive root-owned resources.
The administrative tool accepts a target describing the information requested. One supported resource is the root SSH key:
{
"name": "ops._admin_dump",
"arguments": {
"target": "ssh_keys",
"confirm": true
}
}
The application then reads the root-owned SSH private key, which is possible because OPSMCP runs as root and can read /root/*. The application therefore becomes a credential-disclosure primitive.
After recovering the authorized-lab SSH credential, store it with restrictive permissions:
chmod 600 <ROOT_KEY>
Verify the resulting authentication context:
whoami
id
Final privilege level: root 🎉
┌──────────────────────────────┐
│ MCPJam Inspector │
│ TCP/6274 │
└──────────────┬───────────────┘
│ CVE-2026-23744
▼
┌──────────────────────────────┐
│ Initial RCE │
└──────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ JupyterLab │
│ 127.0.0.1:8888 │
└──────────────┬───────────────┘
│ Token disclosure
▼
┌──────────────────────────────┐
│ Jupyter Kernel │
│ WebSocket RCE │
└──────────────┬───────────────┘
▼
User
│ Source review
▼
┌──────────────────────────────┐
│ OPSMCP │
│ 127.0.0.1:5000 │
│ root │
└──────────────┬───────────────┘
│ API key + hidden tool
▼
┌──────────────────────────────┐
│ Root Credential Leak │
└──────────────┬───────────────┘
▼
root
| System | Watch for |
|---|---|
01 — Developer tooling is attack surface Tools designed for local development can become critical vulnerabilities when exposed to untrusted networks.
02 — Jupyter tokens are powerful credentials Access to a Jupyter token can provide much more than UI access — kernel APIs can provide arbitrary code execution.
03 — Hidden does not mean secure An undocumented endpoint is not an authorization mechanism.
04 — Source code is valuable post-exploitation Application source can reveal authentication mechanisms, secrets, hidden functionality, and privilege boundaries immediately.
05 — Least privilege can break attack chains If OPSMCP had been running as an unprivileged service account, the final impact would have been significantly reduced.
This repository is intended for authorized security research, penetration testing, and educational purposes only. Do not use the techniques described here against systems without explicit authorization.
⚡ MCPJam → RCE → Jupyter → User → OPSMCP → root ⚡
| Step | Stage |
|---|
| 1 | MCPJam Inspector exposed on the network |
| 2 | CVE-2026-23744 exploited |
| 3 | Initial RCE achieved |
| 4 | JupyterLab token disclosed |
| 5 | Jupyter kernel execution |
| 6 | User-level shell |
| 7 | OPSMCP source-code review |
| 8 | Hardcoded API credential discovered |
| 9 | Hidden administrative functionality abused |
| 10 | Root credential disclosed |
| 11 | root |
| # | Weakness | Impact |
|---|
| 1 | Exposed MCPJam Inspector | Remote attack surface |
| 2 | CVE-2026-23744 | Initial RCE |
| 3 | Token in process arguments | Credential disclosure |
| 4 | Jupyter kernel access | User-level code execution |
| 5 | Readable application source | Credential discovery |
| 6 | Hardcoded OPSMCP API key | API authentication bypass |
| 7 | Hidden admin functionality | Privileged operation |
| 8 | OPSMCP running as root | Full system compromise |
| MCPJam |
| Unexpected configuration changes · suspicious child processes · unusual remote clients |
| JupyterLab | Unexpected token usage · unexpected kernel creation · abnormal WebSocket connections · shell processes spawned by kernels |
| OPSMCP | Undocumented tool invocation · credential-related requests · unexpected API clients · administrative operations |
| SSH | Unexpected root logins · new SSH keys · unusual authentication sources |