0–5 min: map listeners
List IPv4/IPv6 sockets, protocols, bind addresses, published container ports, intended clients, and owners.
Success checkEvery listener has an explicit purpose and expected reachability.
Local service security checklist · Updated 2026-07-05
A practical security checklist for desktop apps, agent tools, self-hosted utilities, and container-backed local APIs that expose HTTP or WebSocket services on a developer machine.
Local services are often trusted too much because they run on a developer machine. That assumption is unsafe. A browser tab, malicious extension, compromised desktop renderer, another local process, container, LAN peer, or misconfigured port publication can reach a local HTTP or WebSocket endpoint depending on binding, authentication, browser policy, and network configuration.
This checklist connects RepoDaily coverage of Docker Desktop, Podman, Colima, Apple container, Tauri, Electron, and DeerFlow into one local-service threat model: bind narrowly, authenticate privileged operations, validate browser origins, protect WebSocket handshakes and messages, inventory published ports, separate discovery from authorization, limit container and host access, clean up service state, and retain enough incident evidence to reconstruct abuse.
RepoDaily verdict
Do not treat loopback as authentication and do not treat CORS as authorization. A production-quality local service should have an explicit bind policy, per-client or per-session authentication where privilege exists, strict origin validation for browser-facing flows, separate WebSocket controls, narrow APIs, bounded payloads and rate limits, deterministic startup/shutdown behavior, port and endpoint inventory, container publication review, and incident logs that avoid leaking secrets.
| Surface | Baseline rule | Failure signal | Evidence to keep |
|---|---|---|---|
| Bind address | Bind only to the interfaces the use case needs | 0.0.0.0 or [::] used by default for a local-only service | Configured address, actual listening sockets, owner |
| Authentication | Authenticate privileged API calls even on localhost | Possession of local network reachability is enough to act | Auth method, token scope, rotation path |
| CORS | Use an exact origin allowlist for browser clients | Wildcard origin or reflected Origin with credentials | Allowed origin list and negative tests |
| Origin validation | Validate full scheme/host/port for browser and WebSocket handshakes | Substring matching or no Origin check | Origin policy and rejection logs |
| WebSockets | Authenticate handshake/session and validate every message | Open socket after page load with no message authorization | Handshake checks, message schema, max payload |
| Port publication | Publish only required ports and bind them narrowly | Container port unintentionally reachable from LAN | Port inventory and network scan result |
| Port discovery | Discovery reveals location, not authority | Anyone who finds the port can control the service | Discovery mechanism and auth boundary |
| API surface | Expose narrow task operations | Generic shell, filesystem, SQL, proxy, or arbitrary fetch endpoints | Endpoint inventory and denied-action tests |
| Lifecycle | Start on demand, stop predictably, clean credentials and temp state | Zombie service or stale token survives app exit | PID/session owner, shutdown test, cleanup proof |
| Logging | Record security-relevant events with redaction | No trace of auth failures or logs contain tokens and payload secrets | Event schema, retention, redaction test |
| Containers | Review published ports, mounts, sockets and container network reachability | Broad host mount or daemon socket reachable from local API | Compose/runtime config and privilege review |
Score the service before exposing it to a desktop UI, browser flow, agent runtime, or container-backed app.
| Control | 0 points | 1 point | 2 points | Owner question |
|---|---|---|---|---|
| Network exposure | All interfaces | Loopback configured | Loopback or explicit interface plus verified socket/scan evidence | Who can reach the service from host and LAN? |
| Authentication | None | Shared static token | Scoped session/client auth with rotation and expiry | What proves a caller is authorized? |
| Browser origin policy | Any origin | Manual allowlist | Exact allowlist with tests and separate credential policy | Which websites can invoke the service? |
| WebSocket security | No checks | Handshake auth only | Origin + auth + per-message authorization + limits | What happens after a socket is established? |
| API least privilege | Generic powerful API | Some wrappers | Narrow typed operations with validation and denied tests | What is the smallest operation the client actually needs? |
| Container boundary | Broad mounts/socket | Some restrictions | Explicit ports, mounts, networks, non-root where practical, no unnecessary daemon socket | Can service compromise become host compromise? |
| Lifecycle | Always on/zombie risk | Manual cleanup | Owned startup, health, shutdown, token invalidation and temp cleanup | Who stops and resets the service? |
| Incident evidence | No useful logs | Request logs only | Auth/origin/admin events, correlation IDs, redaction and retention | Can we reconstruct an unauthorized action? |
Use this before connecting a browser, desktop renderer, agent, or container workflow to a local service.
List IPv4/IPv6 sockets, protocols, bind addresses, published container ports, intended clients, and owners.
Success checkEvery listener has an explicit purpose and expected reachability.
Probe from the host, another local process context, and a LAN peer where applicable.
Success checkActual exposure matches the documented bind policy.
Use an unapproved origin to test HTTP requests, credentialed requests, preflight behavior, and WebSocket handshake rejection.
Success checkUnauthorized origins cannot perform privileged actions or establish trusted sockets.
Try missing, expired, wrong-scope, replayed, and malformed credentials plus unauthorized endpoint/message actions.
Success checkThe service rejects calls before side effects and logs useful evidence.
Review mounts, sockets, published ports, arbitrary URL fetches, shell, filesystem and container-control methods.
Success checkNo unnecessary path from local API compromise to broad host privilege exists.
Exit the UI, crash the service, restart it, invalidate tokens, check stale sockets, temp state and security logs.
Success checkThe service returns to a known state and incident evidence is useful without leaking secrets.
| Scenario | Required controls | Stop condition |
|---|---|---|
| Desktop app companion API | Loopback bind, per-session auth, exact renderer origin policy, narrow methods, app-owned lifecycle | Any local webpage or process can call privileged methods unauthenticated |
| Browser-to-localhost developer tool | Explicit origin allowlist, CSRF-resistant auth, no wildcard credentials, strict endpoint scope | Arbitrary website can trigger local state changes |
| Local WebSocket agent gateway | Origin validation, authenticated handshake, per-message authorization, payload and connection limits | Any origin can connect or authenticated socket can invoke unrestricted messages |
| Container-backed local API | Explicit loopback publication, no unnecessary LAN bind, scoped credentials, mount/socket review | Published port or daemon socket exposes host-level privilege |
| Self-hosted dashboard on LAN | Explicit LAN bind, real user auth, TLS where appropriate, session controls, rate limits, audit events | LAN reachability is treated as identity |
| Local model endpoint | Client authentication for sensitive prompts/data, request limits, retention policy, no broad file/tool proxying | Any local process can exfiltrate private context or invoke tools |
| Temporary test server | Random or reserved port, loopback, short lifetime, no production secrets, deterministic cleanup | Server remains after test or binds all interfaces |
| Agent controlling containers | Narrow broker API, explicit allowed actions, no general daemon socket exposure, action logs | Compromised client can create privileged containers or mount arbitrary host paths |
Other local processes and browser-mediated attacks may still reach localhost. Loopback narrows network exposure but does not authenticate the caller.
CORS controls browser read access and request behavior; non-browser clients ignore it, and permissive configurations can expose privileged local APIs.
A service may protect HTTP endpoints yet accept WebSocket handshakes from arbitrary origins, creating a cross-site request channel.
Container port publication can make a local service reachable from interfaces beyond localhost when the host IP is not specified narrowly.
An unpredictable port can reduce accidental discovery but cannot replace authentication because malware, browser behavior, logs, process inspection, or port scans can reveal it.
Endpoints for arbitrary shell commands, filesystem paths, URLs, SQL, container operations, or proxying turn a small local service into a broad privilege bridge.
Background processes, crash recovery, sleep/wake, and failed shutdown can leave reachable services or valid credentials after the UI exits.
Debug logs that capture Authorization headers, session tokens, prompts, file contents, or WebSocket payloads can create a second data-exposure channel.
Use loopback binding to reduce network reachability and a separate authentication mechanism to prove client authority.
Compare complete normalized origins including scheme, host, and port; reject substring and suffix tricks.
Issue short-lived tokens tied to a service instance, client, or capability instead of one permanent machine-wide secret.
Expose startTask, openProject, renderPreview, or runApprovedJob rather than exec, readAnyFile, proxyUrl, or raw container-daemon operations.
Generate or maintain a machine-readable list of listeners, protocols, bind addresses, auth requirements, owners, and intended clients.
Make one parent process or service manager responsible for startup, health, shutdown, token invalidation, and cleanup.
Record authentication failures, origin rejects, privileged actions, config changes, restarts, and abnormal disconnects with correlation IDs and redaction.
Short answers for teams operating localhost and LAN services.
No. It is an important network boundary, but privileged operations still need an authorization model because other local processes and browser-mediated attack paths may reach localhost.
Not by itself. CORS is enforced by browsers and does not authenticate callers. Use strict origins for browser flows plus real authentication and authorization for privileged APIs.
Yes. Validate Origin during the handshake, authenticate the connection, authorize message actions, validate schemas, bound payloads and rate, and log security-relevant events.
It can reduce collisions and casual discovery, but it should not be the main authorization boundary. Ports can be discovered through scans, logs, process inspection, browser behavior, or compromised local software.
A service intended only for the host can become reachable from the LAN or other networks depending on publication settings and host configuration. Verify actual bind scope rather than assuming container isolation.
Record authentication failures, rejected origins, privileged operations, configuration changes, lifecycle events, errors and correlation IDs, while redacting tokens, secrets and sensitive payload contents.
Feedback
Anonymous feedback helps RepoDaily improve what is actually useful.