logo

Port 8000 – HTTP-Alt (Django, Python & Development Web Servers)

Service:

Python http.serverDjango runserveruvicorn/gunicorn (FastAPI/Flask)dev web apps and APIs

Protocol:

TCP

Port:

8000

Used for:

Running development and alternative HTTP web servers and APIs — Python http.server, Django's runserver, uvicorn/gunicorn dev backends, and internal admin dashboards

Port 8000 has no single standard service — it is the web world’s default “second HTTP port,” the number developers reach for the moment port 80 is taken or would need root. Python’s http.server (the old SimpleHTTPServer) serves the current directory over HTTP on 8000; Django’s runserver binds 127.0.0.1:8000 by default; uvicorn, gunicorn, and the FastAPI / Flask development servers commonly land here; Node and other backends borrow it; and it’s a frequent alt-HTTP for reverse proxies, REST APIs, and internal admin dashboards. IANA only lists it informally as “http-alt,” alongside 8080. Because so many unrelated things answer on 8000, the first job on an open port isn’t to attack a known protocol — it’s to identify what web app is answering, then test it as that app. Most often it’s a development server that was never meant to face the internet.

Why It’s Open

Port 8000 is open because a web application chose it. Unlike 80 or 443, binding a port below 1024 needs root on Unix, so developers and frameworks default to high ports like 8000 for anything that runs unprivileged during development:

  • Python http.server / SimpleHTTPServerpython3 -m http.server serves the current working directory over HTTP on 8000 by default, directory listing and all.
  • Django runserver — the development server defaults to 127.0.0.1:8000; countless tutorials and Docker images expose it, and runserver 0.0.0.0:8000 puts it on every interface.
  • uvicorn / gunicorn / FastAPI / Flask — ASGI/WSGI dev servers and the FastAPI + uvicorn default (uvicorn app:app listens on 8000) commonly bind here.
  • Node, PHP, and other backends — dev backends and API servers frequently pick 8000 (or the 8000–8010 range) when 80 and 8080 are busy.
  • Alt-HTTP for proxies, APIs, and admin UIs — reverse proxies, REST/GraphQL APIs, and internal admin dashboards are routinely published on 8000 as a “non-standard” port.

On a laptop an open 8000 is usually a dev server bound to localhost. On a cloud VM or container with 0.0.0.0:8000 and a permissive security group, that same dev server is on the public internet — which is where the risk starts.

Common Risks

  • Exposed development servers. Django’s runserver, Flask, and other dev servers are explicitly “not for production” — they ship without authentication, TLS, rate limiting, or hardening and are meant for localhost. Reachable from the internet, they are an open door.
  • Django DEBUG=True information disclosure. With debug on, any unhandled error returns a full traceback that leaks source code, local variables, the loaded settings, installed apps, framework/Python versions, and database connection details — and frequently the SECRET_KEY, tokens, or credentials that surface in a traceback’s local variables. It’s a fingerprinting and often a key-compromise goldmine.
  • Interactive debugger RCE. Flask/Werkzeug’s debugger console (and Django’s RunServerPlus extension) lets anyone who reaches an error page execute arbitrary Python in the app’s context. Exposed on 8000, that is remote code execution by design — see the CVEs and the Patreon example below.
  • Directory listing / file disclosure. python -m http.server on 8000 serves the entire directory tree it was started in — launch it in the wrong folder and you’re handing out source, configs, .env files, and keys.
  • Dev/internal APIs shipped to prod. Test endpoints, unauthenticated admin routes, and auto-generated API docs (Swagger/OpenAPI at /docs) left reachable on 8000 expose functionality that was never meant to be public.
  • No TLS. Services on 8000 almost always speak plaintext HTTP, so credentials, session tokens, and API keys 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 8000 is identifying the web app before you test it. Confirm HTTP, fingerprint the stack, then branch on what answers.

Confirm the port and detect the service

Terminal window
nmap -sV -p 8000 <target>

Read the HTTP headers and status

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

The Server header usually names the stack: Server: WSGIServer/0.2 CPython/3.x is Django’s runserver, Server: Werkzeug/x.y Python/3.x is Flask/Werkzeug, Server: uvicorn is a FastAPI/ASGI app, and Server: SimpleHTTP/0.6 Python/3.x is http.server. Each points at a different test path.

Fingerprint the framework

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

Trigger a Django debug page (information disclosure)

Terminal window
curl -s "http://<target>:8000/this-path-should-404"

If the response is a styled Django debug page listing URL patterns, installed apps, and the settings/traceback, DEBUG=True is on and exposed — force a 500 (bad input to a real view) to get the full traceback with local variables.

Enumerate paths, APIs, and dev docs

Terminal window
gobuster dir -u http://<target>:8000/ -w /usr/share/wordlists/dirb/common.txt
nmap --script http-enum -p 8000 <target>

Look specifically for /docs, /openapi.json, /redoc (FastAPI), /admin (Django), /api, and /debug.

Exploit an exposed Werkzeug / Flask debugger

Terminal window
msfconsole -q
use exploit/multi/http/werkzeug_debug_rce
set RHOSTS <target>
set RPORT 8000
run

Log every open port 8000, the exact web app you fingerprinted, and any exposed debugger, debug page, or unauthenticated endpoint straight into the pentest report instead of a scratch terminal you’ll lose.

What to Look For

Checkpoint What it means
Server: WSGIServer/... CPython banner Django runserver dev server — check for DEBUG=True and an open /admin
Server: Werkzeug/... Python banner Flask/Werkzeug — probe for an exposed interactive debugger (RCE)
Server: uvicorn or SimpleHTTP/... Python FastAPI/ASGI app or python http.server — test as that specific stack
Django traceback / settings shown on error DEBUG=True exposed — source, config, and secrets leak
Directory listing (“Index of /”) python http.server serving a folder — hunt for .env, keys, source
/docs, /openapi.json, /redoc reachable FastAPI dev API and schema exposed — map every endpoint
No auth / no login on admin or API Anyone can reach the dashboard, API, or underlying data
Plaintext HTTP only (no TLS) Credentials and tokens sniffable on the wire
Reachable from the internet A localhost-intended dev server exposed beyond its scope

Known CVEs and Exploits

There is no generic “port 8000” CVE — the flaws that matter belong to whatever web app is listening. The honest first step is to fingerprint the exact server and version, then check that product’s advisories. The verified CVEs most relevant to the dev servers that habitually bind 8000 are:

  • CVE-2024-34069 — Werkzeug debugger remote code execution (CSRF-based) in versions before 3.0.3. CVSS 7.5. Even with PIN protection, an attacker who lures a developer to a malicious domain can drive the debugger console to execute code on the developer’s machine. The classic higher-impact case is simpler: a Werkzeug/Flask debugger left exposed with no PIN is direct RCE — weaponised in Metasploit as exploit/multi/http/werkzeug_debug_rce, which lists 8000 among its default target ports.
  • CVE-2021-28861 — open redirect (CWE-601) in Python’s http.server (lib/http/server.py) through Python 3.10.x. CVSS 7.4 (NVD marks it disputed, since http.server is documented as not for production). A URL path starting with // redirects the client to an attacker-controlled host — phishing and information disclosure from the very python -m http.server people run on 8000.
  • CVE-2020-7695 — HTTP response splitting in Uvicorn before 0.11.7. CVSS 5.3. Unescaped CRLF sequences in header values let crafted input inject arbitrary headers or an entire response body against a FastAPI/uvicorn app.

For a Django, Node, or custom app on 8000, the CVEs that matter are that specific product and version’s — not “port 8000’s.” And the biggest real-world risk here is usually not a CVE at all but a design decision: an unauthenticated development server with debug on, reachable from the internet.

The previous version of this page listed four “port 8000” vulnerabilities that were all mislabeled and have been removed. CVE-2019-8331 is a Bootstrap XSS bug, not a “Django debug page RCE”; CVE-2019-17626 is a ReportLab eval() RCE, not a Werkzeug/Flask debugger flaw; CVE-2020-5260 is a Git credential-injection bug, not “Django logs”; and Exploit-DB 47837 is the nostromo 1.9.6 web-server RCE (CVE-2019-16278), not a “Python http.server directory traversal.” Always verify a CVE against its NVD record and scope it to the actual service before trusting it.

Mitigation

  • Identify the real app first. You can’t secure “port 8000” generically — fingerprint whether it’s Django, Flask, FastAPI, http.server, or a custom backend, then harden that specific thing.
  • Never run a dev server in production. Django’s runserver, Flask/Werkzeug, and uvicorn --reload are for development only. Serve real traffic through gunicorn/uvicorn workers behind a proper reverse proxy, not the built-in dev server.
  • Turn off debug everywhere it can be reached. Set DEBUG=False in Django and never enable the Werkzeug/Flask debugger (use_evalex) on anything an untrusted network can touch — an exposed debugger is remote code execution.
  • Bind to localhost, not 0.0.0.0. Keep dev servers on 127.0.0.1:8000; if remote access is genuinely needed, front them with a reverse proxy that adds authentication and TLS on 443 or 8443.
  • Don’t serve directories you don’t mean to. Never run python -m http.server in a home, source, or secrets directory on an exposed host.
  • Require auth on every API and admin route, remove test/debug endpoints before shipping, and gate auto-generated API docs (/docs, /openapi.json) behind authentication in production.
  • Firewall 8000 to the clients that actually need it, and audit cloud security groups and container port mappings for an accidental 0.0.0.0:8000. The related alt-HTTP ports 8080 and 8443 deserve the same review, and confirmed findings belong in your pentest report.
  • Patch the framework: keep Werkzeug ≥ 3.0.3, Uvicorn ≥ 0.11.7, and Python and Django current.

Real-World Example

Patreon’s 2015 breach is the cleanest illustration of why an exposed dev server on 8000 is the whole attack surface. In September 2015 the crowdfunding platform was compromised after leaving a debug build of its application publicly reachable with the Werkzeug debugger enabled. Because Werkzeug’s interactive debugger exposes a Python console on its error pages — anyone who reaches it can run arbitrary code in the app’s context — the exposed endpoint (visible on Shodan for weeks, and reported to Patreon by researchers before the breach) was effectively an unauthenticated remote shell. Attackers used it to run code on the server and exfiltrated roughly 15 GB of data — names, email addresses, and donation records — which was then published online. The port and the framework were mundane; a development server with debug left on and pointed at the internet was the entire compromise.

FAQ

What is port 8000 used for?

Port 8000 is an unofficial “HTTP-alternative” web port with no single standard service. It’s the default for Python’s http.server, Django’s runserver (127.0.0.1:8000), and uvicorn/FastAPI dev servers, and a common pick for Node backends, REST APIs, reverse proxies, and internal admin dashboards. On an open 8000, the first step is to identify which web app is actually answering.

Why is port 8000 open on my computer?

Almost always because a web development server is running. python -m http.server, django-admin runserver, uvicorn, and similar tools bind 8000 by default. It’s usually meant to be reachable only from your own machine (127.0.0.1) — if it’s listening on 0.0.0.0 and your firewall allows it, it may be exposed to the whole network.

Is port 8000 safe to leave open?

The port itself is harmless; the risk is what’s behind it. A properly deployed app behind a reverse proxy with authentication and TLS is fine. A development server — especially Django with DEBUG=True or a Flask/Werkzeug debugger — exposed to an untrusted network is dangerous: it can leak source and secrets or hand over remote code execution. Don’t publish 8000 without knowing exactly what answers on it.

What’s the difference between port 8000 and 8080?

Both are unofficial “http-alt” ports used when 80 is taken. In practice 8000 leans toward application and dev servers (Python/Django/FastAPI), while 8080 is more associated with proxies, Java app servers like Tomcat, and web front-ends — but neither is a rule. Fingerprint the actual service on either port rather than assuming from the number.

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

Fingerprint it: curl -sI http://<host>:8000/ to read the Server header, nmap -sV -p 8000 <host> for a version scan, and whatweb http://<host>:8000/ to identify the stack. A WSGIServer banner is Django’s runserver, Werkzeug is Flask, uvicorn is FastAPI/ASGI, and SimpleHTTP is Python’s http.server — each tells you how to test it.

How do I secure or close port 8000?

Set DEBUG=False, disable any interactive debugger, bind dev servers to 127.0.0.1, and serve production traffic through gunicorn/uvicorn behind a reverse proxy with authentication and TLS. Require auth on all APIs and admin routes, remove debug/test endpoints, and firewall 8000 to the clients that need it. If nothing needs it, stop the service and confirm with nmap -p 8000 <host>.

TL;DR

  • Service: no single standard — an HTTP-alt / development web port. Most often Python http.server, Django runserver (127.0.0.1:8000), uvicorn/gunicorn (FastAPI/Flask), or a custom API/admin UI
  • Default port: 8000/TCP (plaintext HTTP; sibling alt-HTTP ports 8080 and 8443)
  • Biggest risk: an exposed, unauthenticated development server — Django DEBUG=True leaking source and secrets, or a Flask/Werkzeug debugger that gives remote code execution — reachable from the internet
  • Mitigation: identify the real app, set DEBUG=False, disable debuggers, bind to localhost, serve production through a reverse proxy with auth and TLS, and firewall 8000 to the clients that need it