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