Service:
Docker RegistryFlask/PythonAirPlay/Control CenterUPnPSynology DSMProtocol:
TCP/UDPPort:
5000Used for:
Hosting a Docker Registry, a Flask or Python dev server, macOS AirPlay/Control Center, or other self-hosted appsPort 5000 has no single standard service — depending on the host, it commonly runs a self-hosted Docker Registry, a Flask (or other Python) development server, or, on a Mac, Apple’s AirPlay Receiver / Control Center. Synology’s DSM web interface, some devices’ UPnP endpoints, and a long tail of internal apps use it too. Because so many different things bind here, the first job on an open port 5000 isn’t to attack a known protocol — it’s to identify what is actually answering and then assess that specific service. An exposed Docker Registry leaking container images and baked-in secrets, or a Flask app left in debug mode, is a classic finding; a Mac quietly advertising AirPlay on 5000 is usually benign.
Why It’s Open
Port 5000 is a default that several unrelated tools reach for:
- Docker Registry. The official self-hosted registry image (
registry:2) listens on 5000 out of the box. Teams run it to store and distribute their own container images, and it is the single most security-relevant occupant of this port. - Flask and Python dev servers. Flask’s built-in development server binds
127.0.0.1:5000by default, and countless tutorials run it asflask run --host=0.0.0.0— which publishes it to the whole network. Django and other Python apps are often pointed at 5000 as well. - macOS AirPlay / Control Center. On modern macOS the AirPlay Receiver and Control Center listen on TCP 5000 (and 7000). This is the most common benign reason a Mac shows 5000 open.
- Synology DSM. DiskStation Manager serves its HTTP web UI on 5000 (HTTPS on 5001) by default.
- UPnP and assorted apps. Some devices expose a UPnP/HTTP endpoint here — its discovery sibling is SSDP on UDP 1900.
On a laptop, Flask or a registry bound to localhost is unreachable from outside — but the same command on a cloud VM, a container, or a CI runner often binds 0.0.0.0:5000, and a published Docker port (-p 5000:5000) or a permissive security group quietly turns it into an internet-facing service. Port 5000 sits right next to the other dev-server catch-all, port 3000, and where either is answering, plain HTTP on port 80 and HTTPS on port 443 are usually one scan away.
Common Risks
- Exposed Docker Registry. A registry with no authentication lets anyone hit
/v2/_catalog, list every repository, and pull images. Those image layers routinely contain source code, config files, API keys, and cloud credentials. If the registry also allows unauthenticated push, an attacker can overwrite a trusted image tag — a direct supply-chain compromise of everything that later pulls it. - Flask / Werkzeug debug mode. When a Flask app runs with
debug=True, Werkzeug serves an interactive traceback console on error pages. If that app is reachable, the console is unauthenticated remote code execution (a PIN was added in later Werkzeug, but it is bypassable in some setups and frequently disabled). - Cleartext HTTP. Traffic on 5000 is almost always plain HTTP, so credentials, API tokens, and session cookies for anything behind it cross the wire unencrypted.
- Information disclosure and default credentials. Custom APIs leak internal logic, environment variables, and stack traces; management UIs like Synology DSM are a valuable target and are sometimes left on default or weak credentials.
- AirPlay attack surface. A Mac’s AirPlay Receiver is usually harmless, but the 2025 “AirBorne” flaws showed that an AirPlay Receiver reachable on an untrusted network can be a real remote-code-execution path (see CVEs below).
Want to save time on reporting?
Let PentestPad generate, track, and export your reports - automatically.

Enumeration & Testing
The whole game on port 5000 is identifying the service before you test it. Start with a version scan, then fingerprint for each likely occupant.
Detect the service and version
nmap -sV -p 5000 <target>nmap -sU -p 5000 <target>Check for a Docker Registry
curl -sI http://<target>:5000/v2/A Docker-Distribution-Api-Version: registry/2.0 header confirms a registry. A 200 with no auth challenge means it’s open — enumerate it:
curl -s http://<target>:5000/v2/_catalogcurl -s http://<target>:5000/v2/<repo>/tags/listFingerprint Flask / Werkzeug
curl -sI http://<target>:5000/A Server: Werkzeug/<x> Python/<x> header points to a Flask/Werkzeug dev server. If error pages render an interactive traceback with a console prompt, debug mode is on — flag it (do not execute code against systems you are not authorized to test).
Identify a Mac’s AirPlay Receiver
# AirPlay advertises over mDNS; also check the paired control port 7000dns-sd -B _airplay._tcp local. # avahi-browse -r _airplay._tcp on Linuxcurl -s http://<target>:7000/infoCheck for Synology DSM
curl -s http://<target>:5000/webman/index.cgi | grep -i synologyLog every open instance and finding you confirm so it lands in the final pentest report instead of a scratch file.
What to Look For
| Checkpoint | What it means |
|---|---|
Docker-Distribution-Api-Version header, /v2/ returns 200 |
An open Docker Registry — list and pull images, check for secrets in layers |
/v2/ write/push accepted without auth |
Attacker can poison trusted image tags — supply-chain risk |
Server: Werkzeug + interactive traceback console |
Flask debug mode on — unauthenticated RCE if reachable |
| Custom API with verbose errors or no auth | Leaks internal logic, env vars, and endpoints |
| Synology DSM login page | Management UI — check version and for default/weak creds |
AirPlay/_airplay._tcp on 5000 + 7000 |
Usually a Mac’s Control Center; confirm it’s patched and off untrusted nets |
| Plain HTTP with no TLS | Credentials and tokens are sniffable on the wire |
Known CVEs and Exploits
There is no single “port 5000” CVE — the flaws that matter belong to whatever is listening. The two most common exposures here, an open Docker Registry and a Flask app in debug mode, are usually configuration problems rather than named CVEs, and should be fixed as such.
- Exposed Docker Registry (misconfiguration). No CVE required: a registry started without
htpasswd/token auth and TLS lets anyone list, pull, and sometimes push images. Treat any registry reachable beyond a trusted range as a finding. - Flask / Werkzeug debug console (misconfiguration → RCE). Running
debug=Truein production exposes the Werkzeug interactive debugger, which executes arbitrary Python. Publicly archived as Exploit-DB 48579. - CVE-2019-14806 — Pallets Werkzeug before 0.15.3: insufficient debugger PIN randomness because Docker containers share the same machine ID, weakening the protection meant to guard that debug console. CVSS 7.5.
- CVE-2025-24252 — Apple AirPlay (“AirBorne”) use-after-free; an attacker on the local network can corrupt process memory. Chained with CVE-2025-24206 it becomes zero-click RCE on a Mac whose AirPlay Receiver is set to accept “Anyone on the same network.” Fixed in macOS 15.4 / 14.7.5 / 13.7.5 and iOS 18.4. CVSS 8.8.
- CVE-2025-24206 — Apple AirPlay authentication-policy bypass on the local network; removes the “Accept” prompt and is what makes the AirBorne chain zero-click. CWE-288.
- CVE-2025-24132 — Stack-based buffer overflow in Apple’s AirPlay audio SDK (before 2.7.1), AirPlay video SDK, and CarPlay plug-in, enabling zero-click code execution on third-party AirPlay speakers and receivers.
The previous version of this page cited CVE-2021-21330, CVE-2020-15106, and CVE-2019-15224 as “port 5000” bugs. Those are unrelated (aiohttp open redirect, etcd denial-of-service, and a rest-client Ruby gem backdoor, respectively) and have been removed.
Mitigation
- Identify what runs on 5000 first. You can’t secure the port generically — fingerprint the service (registry, Flask, AirPlay, Synology, UPnP) and harden that specific thing.
- Never expose a Docker Registry unauthenticated. Require auth (
htpasswd, OAuth/token, or a proxy) and TLS, and don’t publish it to the internet at all — keep it on a management network or behind a VPN. - Never run Flask/Werkzeug debug mode in production. Set
debug=False, serve behind a real WSGI server (gunicorn/uWSGI) and a reverse proxy, and bind dev servers to127.0.0.1rather than0.0.0.0. - Keep AirPlay/Control Center off untrusted networks and patched. Update macOS/iOS to a fixed release, set AirPlay Receiver to “Current User” or disable it, and firewall 5000/7000 to trusted devices.
- Harden Synology DSM and any management UI: patch it, enforce strong credentials and 2FA, and keep it off the public internet.
- Firewall port 5000 to trusted management ranges, and audit cloud security groups and container port mappings for an accidental
0.0.0.0:5000.
Real-World Example
Exposed Docker Registries are the signature port-5000 finding. Because registry:2 listens on 5000 by default and the API needs no credentials unless you configure them, teams that publish the port — a -p 5000:5000 in a compose file, a too-broad security group — hand anyone who scans the host a fully browsable registry. The recon is trivial: curl http://host:5000/v2/_catalog lists every repository, .../tags/list enumerates versions, and pulling an image unpacks its layers, which frequently contain hardcoded cloud keys, .env files, and source. Where push is also open, an attacker can retag a backdoored image over a trusted one and wait for the next deployment to pull it — turning a single misconfigured port into a supply-chain foothold. It’s the clearest illustration of the port-5000 lesson: the port is mundane, but whatever happens to be listening on it is the real attack surface.
FAQ
What is port 5000 used for?
Port 5000 has no single standard service. It is the default for a self-hosted Docker Registry (registry:2) and Flask’s development server, the port macOS uses for AirPlay Receiver / Control Center, and the default web UI port for Synology DSM. On an open 5000, the first step is to identify which of these is actually running.
Why is port 5000 open on my Mac?
Modern macOS runs the AirPlay Receiver and Control Center on ports 5000 and 7000. That’s the usual, benign reason a Mac shows 5000 listening. If you don’t use AirPlay to your Mac, you can turn the AirPlay Receiver off in System Settings, which frees the port.
Is port 5000 safe to leave open?
The port itself is harmless; the risk depends on what’s behind it. A Docker Registry or Flask app exposed to the internet on 5000 is a real problem — image and secret disclosure, or debug-mode RCE. A Mac’s AirPlay on a trusted, patched network is usually fine. Don’t publish 5000 to untrusted networks.
How do I check what’s running on port 5000?
Fingerprint it: nmap -sV -p 5000 <host> and curl -sI http://<host>:5000/. A Docker-Distribution-Api-Version header means a registry, Server: Werkzeug means a Flask dev server, an _airplay._tcp mDNS record plus port 7000 means AirPlay, and a Synology login page means DSM.
Is port 5000 TCP or UDP?
Mostly TCP — Docker Registry, Flask, AirPlay control, and Synology DSM all speak HTTP over TCP. It can appear on UDP for some device/UPnP media services, so a full check scans both.
How do I secure or close port 5000?
Identify the service, then lock it down: require auth and TLS on a Docker Registry (or take it off the internet), disable Flask/Werkzeug debug mode and bind dev servers to localhost, patch and restrict Synology DSM, keep AirPlay off untrusted networks, and firewall the port to trusted hosts. If nothing needs it, stop the service and confirm the port is closed with a rescan.
TL;DR
- Service: no single standard — most often a self-hosted Docker Registry, a Flask/Python dev server, or (on a Mac) AirPlay/Control Center; also Synology DSM and UPnP
- Default port: 5000/TCP (some UDP device services; AirPlay also uses 7000)
- Biggest risk: an exposed Docker Registry (image and secret disclosure, push → supply-chain) and Flask debug-mode RCE
- Mitigation: identify the service, require auth + TLS on registries, disable debug mode, patch AirPlay/Synology, and firewall port 5000