logo

Port 8888 – Jupyter Notebook and Alt-HTTP Dev Servers (Jupyter, Cloud IDEs, HTTP Proxies)

Service:

Jupyter Notebook / JupyterLabdevelopment web serversHTTP debugging proxies (Fiddler)Cloud9/IDE-in-browser and app dashboards

Protocol:

TCP

Port:

8888

Used for:

Serving Jupyter Notebook and JupyterLab, plus a range of development web servers, HTTP debugging proxies, and browser-based IDE and app dashboards, over an alternate HTTP port

Port 8888 has no single standard service — it is one of the web world’s favourite “alt-HTTP” ports, and its flagship occupant is Jupyter Notebook / JupyterLab, the browser-based interactive computing environment that data scientists live in. jupyter notebook and jupyter lab both bind localhost:8888 by default, serving a web UI where any cell can run arbitrary Python (or R, Julia, shell) on the host. Plenty of other tools reach for 8888 too: the Fiddler web-debugging proxy listens here by default, assorted development web servers and HTTP/tunneling proxies pick it when the usual ports are taken, and browser-based IDEs (Cloud9-style) and app dashboards publish on it as a “non-standard” port. Because so many unrelated things answer on 8888, the first job on an open port isn’t to attack a known protocol — it’s to identify what is answering, and then test it as that. Most often it’s a Jupyter server that was meant to stay on localhost, and the single most damaging finding in this whole space is a Jupyter server reachable from the internet with no token or password.

Why It’s Open

Port 8888 is open because a development tool chose it. Binding a port below 1024 needs root on Unix, so interactive and dev tooling defaults to high ports — and 8888 is a memorable, rarely-reserved one:

  • Jupyter Notebook / JupyterLabjupyter notebook and jupyter lab default to http://localhost:8888/, and JupyterHub spawns single-user servers in the same range. This is the dominant real-world use of 8888. A notebook is, by design, a remote code-execution console with a web front end: every cell you run executes on the server as the user that launched it.
  • Fiddler and other HTTP proxies — Telerik Fiddler (Classic) listens on 8888 by default, and various tunneling, caching, and anti-censorship HTTP proxies use it as their listen port. An open 8888 that behaves like a forward proxy is a very different finding from a Jupyter server.
  • Development web servers — Node, Python, and other dev backends frequently land on 8888 (or the 8080–8888 range) when 80, 8000, and 8080 are already busy.
  • Browser-based IDEs and app dashboards — Cloud9-style IDE-in-browser tools, admin dashboards, and internal apps are routinely published on 8888 as an alternate HTTP port.

On a laptop an open 8888 is usually a Jupyter server or a proxy bound to 127.0.0.1. On a cloud VM or container started with --ip=0.0.0.0 and a permissive security group, that same notebook is on the public internet — which is exactly where the risk starts.

Common Risks

  • Exposed Jupyter with no authentication = instant RCE. A Jupyter server started with --NotebookApp.token='' --ip=0.0.0.0 (or reached before its token is set) hands anyone who finds it a web console. Open a notebook, run import os; os.system('id'), and you have code execution as the server’s OS user. This misconfiguration — not any CVE — is the biggest risk on this port, and it is actively hunted at internet scale.
  • Cloud-credential theft and lateral movement. Jupyter servers usually run in cloud workloads with an attached IAM role. Code execution in a notebook means the attacker can read the cloud metadata endpoint (169.254.169.254), steal temporary AWS/GCP/Azure credentials, and pivot into the wider account.
  • Cryptomining and fileless malware. Exposed notebooks are a favourite target for cryptomining campaigns (see the PyLoose and Qubitstrike examples below) that load miners straight into memory and harvest credentials.
  • XSS-to-RCE in the notebook UI. Older Jupyter Notebook/JupyterLab builds mishandle untrusted .ipynb content, so simply opening a malicious notebook can execute code (see the CVEs below).
  • Token and cookie leakage. Jupyter’s access token often ends up in the URL, shell history, process list, logs, or a referrer header — capture it and you have full authenticated access. Some versions log auth cookies on server errors.
  • Open proxy abuse. If 8888 is a forward proxy (Fiddler or similar) left listening on all interfaces, attackers can relay traffic through it to reach internal hosts or launder their own requests.
  • No TLS. Services on 8888 almost always speak plaintext HTTP, so tokens, notebook contents, and credentials cross the wire in the clear.

Want to save time on reporting?

Let PentestPad generate, track, and export your reports - automatically.

logo-cta

Enumeration & Testing

The whole game on 8888 is identifying the service before you test it — Jupyter, a proxy, or a custom app all need different handling. Confirm HTTP, fingerprint the stack, then branch on what answers.

Confirm the port and detect the service

Terminal window
nmap -sV -p 8888 <target>

Read the HTTP headers and status

Terminal window
curl -sI http://<target>:8888/

Jupyter servers run on Tornado, so a Server: TornadoServer/x.y.z header is a strong Jupyter fingerprint. A Content-Type of text/html with a redirect to /login also points at Jupyter. A proxy or another dev stack shows a different banner.

Query the Jupyter REST API

Terminal window
curl -s http://<target>:8888/api
curl -s http://<target>:8888/api/status

/api returns a JSON version object (e.g. {"version": "6.4.0"}) that identifies the exact Jupyter build so you can map it to the CVEs below.

Check whether authentication is actually enforced

Terminal window
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://<target>:8888/tree
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://<target>:8888/lab

/tree is the classic Notebook dashboard and /lab is JupyterLab. A 302 redirect to /login?next=... means token/password auth is on. A 200 that returns the dashboard directly means there is no auth — anyone can open a notebook and run code. Look for a token= value in the URL, referrer headers, or exposed logs; with the token you get full access.

If auth is off, list the code-execution surface

Terminal window
curl -s http://<target>:8888/api/kernels
curl -s http://<target>:8888/api/sessions
curl -s http://<target>:8888/api/contents
curl -s http://<target>:8888/api/terminals

Reachable kernels, sessions, contents, and especially terminals endpoints confirm an interactive execution surface: from here an attacker can create a kernel and run arbitrary code, or open a web terminal for a direct shell. (The proof-of-concept for an unauthenticated Jupyter is simply opening the web UI, creating a notebook, and running import os; os.system('id') — there is no exploit module because there is nothing to exploit; it is working as configured.)

Fingerprint a non-Jupyter service or proxy

Terminal window
whatweb http://<target>:8888/
nmap --script http-title,http-headers -p 8888 <target>

A text/html app that isn’t Jupyter is a custom dashboard or IDE — test that stack. If the service instead forwards your request to an arbitrary upstream, you’re looking at an open HTTP proxy (Fiddler or similar), which is its own finding.

Log every open port 8888, the exact service and version you fingerprinted, whether authentication was enforced, and any token you captured straight into the pentest report instead of a scratch terminal you’ll lose.

What to Look For

Checkpoint What it means
Server: TornadoServer banner / /api returns a version JSON A Jupyter server (Notebook or JupyterLab) — record the version and test its auth
/tree or /lab returns the dashboard directly (HTTP 200) No token/password — anyone can open a notebook and run code (RCE)
Redirect to /login?next= Token or password auth is enabled — hunt for a leaked token before assuming it’s safe
token= in the URL, referrer, shell history, or logs Full authenticated access if captured
/api/terminals or /api/kernels reachable unauthenticated Interactive shell / arbitrary code-execution surface exposed
Server can reach 169.254.169.254 from a kernel Cloud metadata and IAM credentials at risk of theft
Request gets forwarded to an arbitrary upstream host An open HTTP proxy (e.g. Fiddler) — internal-network and relay abuse
Other HTTP banner (custom app, browser IDE) A non-Jupyter dev tool — fingerprint and test that specific stack
Plaintext HTTP only (no TLS) Tokens and notebook data sniffable on the wire
Reachable from the internet A localhost-intended dev tool exposed beyond its scope

Known CVEs and Exploits

The most important thing to say about port 8888 is that its worst-case risk is not a CVE at all — it’s a misconfiguration: a Jupyter server exposed with no token or password, which is direct, unauthenticated remote code execution by design. There is no exploit module for it because nothing needs to be exploited. That said, several verified Jupyter CVEs matter once you’ve fingerprinted the version, mostly turning a malicious notebook or link into code execution or token theft:

  • CVE-2021-32798 — Jupyter Notebook 5.7.0–5.7.10 and 6.0.0–6.4.0 use a deprecated, bypassable Google Caja sanitizer, so an untrusted notebook can execute code on load. A public Caja bypass triggers XSS when a victim opens a malicious .ipynb, which in the notebook context escalates to code execution. CVSS 9.6 (Critical). Fixed in 6.4.1.
  • CVE-2021-32797 — JupyterLab (< 1.2.1, 2.x < 2.2.10 / < 2.3.2, 3.x < 3.0.17 / < 3.1.4) fails to sanitize the action attribute of an HTML <form>, allowing remote code execution when a user opens a crafted notebook. CVSS 9.6 (Critical).
  • CVE-2022-24757 — Jupyter Server before 1.15.4 writes the auth cookie and other header values into the server logs on any 5xx error (CWE-532). Anyone who can read the logs can steal the session credential and hijack the server. CVSS 7.5 (High).
  • CVE-2024-22421 — JupyterLab (< 3.6.7, 4.0.0–4.0.10, 4.1.0b2) and Jupyter Notebook 7.0.0–7.0.6: a user who clicks a malicious link can leak their Authorization and XSRFToken tokens to a third party when running an older jupyter-server (relative path traversal / information exposure). CVSS 6.5 (Medium).

For Fiddler, a browser IDE, or a custom app on 8888, the CVEs that matter are that specific product and version’s — not “port 8888’s.” And on this port, again, the design-level exposure (an unauthenticated internet-facing notebook) is a bigger and more common problem than any of the above.

The previous version of this page listed three “port 8888” CVEs that were all mislabeled or invalid and have been removed. CVE-2025-3421 is a reflected-XSS bug in the “Everest Forms” WordPress plugin, not a “Jupyter Notebook remote code execution”; CVE-2024-7890 is a local privilege-escalation flaw in Citrix Workspace app for Windows, not a “development server authentication bypass”; and CVE-2023-4567 was rejected by its CNA as non-reproducible (“not a viable flaw”), not a “Jupyter token bypass.” Always verify a CVE against its NVD record and scope it to the actual service before trusting it.

Mitigation

  • Never expose a Jupyter server without authentication. Keep the default token on, or set a strong hashed password (c.ServerApp.password / c.NotebookApp.password). Never start a server with --NotebookApp.token='' --NotebookApp.password='' on anything an untrusted network can reach.
  • Bind to localhost and reach it over a tunnel. Run notebooks on --ip=127.0.0.1 and access remote instances through an SSH tunnel (ssh -L 8888:localhost:8888 <host>) or a reverse proxy that adds authentication and TLS — not --ip=0.0.0.0.
  • Don’t run the kernel as root. Avoid --allow-root; run Jupyter as an unprivileged user inside a container or sandbox, because any code in a notebook runs with the server’s OS privileges.
  • Restrict egress from the workload. Block the kernel’s access to the cloud metadata endpoint (169.254.169.254) and limit outbound traffic so a compromised notebook can’t steal IAM credentials or pull down a miner.
  • Patch Jupyter. Update to Notebook ≥ 6.4.1, JupyterLab ≥ 3.1.4 (and the 4.x fixes), and Jupyter Server ≥ 1.15.4 to close the XSS-to-RCE and token-leak CVEs above.
  • Terminate TLS in front of it. Put the notebook behind a reverse proxy with a real certificate on 443 or 8443 so tokens and data aren’t sent in cleartext.
  • Lock down proxies and dev servers. If 8888 is Fiddler or another proxy, bind it to localhost so it isn’t an open relay; harden custom apps and IDEs like any other web service.
  • Firewall 8888 to the clients that actually need it, and audit cloud security groups and container port mappings for an accidental 0.0.0.0:8888. The sibling alt-HTTP ports 8000, 8080, and 9000 deserve the same review, and confirmed findings belong in your pentest report.

Real-World Example

The PyLoose attack documented by Wiz Research in July 2023 is the cleanest illustration of why an exposed Jupyter on 8888 is the whole attack surface. The victim ran a publicly accessible Jupyter Notebook service that failed to restrict system-command execution through Python modules like os and subprocess. The attacker simply used that access to fetch malicious Python from a paste site over HTTPS — never touching disk — and loaded an XMRig cryptominer directly into memory via Linux’s memfd file descriptor, connecting out to a MoneroOcean pool. Wiz called it the first publicly documented Python-based fileless attack on cloud workloads, and none of it required an exploit: the notebook was doing exactly what notebooks do, for an attacker who was never supposed to reach it.

It isn’t a one-off. In October 2023 Cado Security detailed the Qubitstrike campaign, which scanned for internet-exposed Jupyter Notebooks, deployed cryptominers, and exfiltrated AWS and Google Cloud credentials over Telegram to pivot deeper into victims’ cloud accounts. The pattern is consistent: the port number and the software are mundane, but a Jupyter server left reachable without authentication is an unauthenticated remote shell — and attackers scan for it continuously.

FAQ

What is port 8888 used for?

Port 8888 is an unofficial alternate-HTTP port with no single standard service. Its most common occupant is Jupyter Notebook / JupyterLab, whose web UI defaults to http://localhost:8888/; it’s also the default listen port for the Fiddler debugging proxy and a frequent pick for development web servers, HTTP/tunneling proxies, browser-based IDEs, and app dashboards. On an open 8888, the first step is to identify which of these is actually answering.

Why is port 8888 open on my computer?

Almost always because a development tool is running. Starting jupyter notebook or jupyter lab binds 8888 by default, and Fiddler or a dev server may claim it too. It’s usually meant to be reachable only from your own machine (127.0.0.1) — if the service is listening on 0.0.0.0 and your firewall allows it, it may be exposed to the whole network or the internet.

Is it dangerous to expose Jupyter on port 8888?

Yes. A Jupyter server is an interactive code-execution environment by design: every notebook cell runs on the host as the launching user. If it’s reachable from an untrusted network with no token or password, anyone who finds it gets remote code execution — and, on a cloud VM, a path to your IAM credentials via the metadata endpoint. Never publish a notebook without authentication and TLS.

What’s the difference between port 8888 and ports 8000 or 8080?

All three are “http-alt” ports used when 80 is taken. In practice 8000 leans toward Python/Django-style dev servers, 8080 toward proxies and Java app servers like Tomcat, and 8888 toward Jupyter and debugging proxies like Fiddler — but none of that is a rule. Fingerprint the actual service on any of them rather than assuming from the number.

How do I find out what’s running on my port 8888?

Fingerprint it: curl -sI http://<host>:8888/ to read the Server header (a TornadoServer banner is Jupyter), curl -s http://<host>:8888/api to get the exact Jupyter version, and nmap -sV -p 8888 <host> for a version scan. Then check auth: if http://<host>:8888/tree returns the dashboard instead of redirecting to /login, the server is unauthenticated.

How do I secure or close port 8888?

For Jupyter, keep the token or set a strong password, bind to 127.0.0.1 and reach it over an SSH tunnel or an authenticated TLS reverse proxy, don’t run as root, patch to a current version, and restrict the workload’s egress. For a proxy or app, bind it to localhost and harden it. Firewall 8888 to the clients that need it, and if nothing needs it, stop the service and confirm with nmap -p 8888 <host>.

TL;DR

  • Service: no single standard — most often Jupyter Notebook / JupyterLab (default localhost:8888), also the Fiddler debugging proxy, dev web servers, HTTP proxies, and browser-based IDEs/dashboards
  • Default port: 8888/TCP (plaintext HTTP; sibling alt-HTTP ports 8000, 8080, and 8443)
  • Biggest risk: an exposed Jupyter server with no token/password — unauthenticated remote code execution, cloud-credential theft, and cryptomining — which is a misconfiguration, not a CVE; older builds also carry verified XSS-to-RCE and token-leak CVEs
  • Mitigation: require token/password auth, bind to localhost and tunnel in, don’t run as root, restrict egress to cloud metadata, patch Jupyter, terminate TLS in front, and firewall 8888 to trusted clients