vLLM's --api-key leaves /invocations and a dozen control endpoints unauthenticated, including /pause, /abort_requests and /update_weights
[blocker] operations
Fields
id
gotchas/ops-api-key-covers-only-v1-prefixesClass
operations
Severity
blocker
Concepts
securityauthnauthzmulti-tenantadmin-api
Symptom
An authenticated deployment is bypassable by anyone who can reach the HTTP server: an unauthenticated POST to /invocations runs inference at full capability, an unauthenticated POST to /pause takes the engine out of service, and /abort_requests drops in-flight work for every tenant. None of this requires a credential, and none appears in a failed-auth log. An operator who has verified that --api-key rejects a bad token concludes the endpoint is protected and has not.
Root cause
--api-key / VLLM_API_KEY authenticates ONLY the /v1, /v2, /inference and /cohere path prefixes — it is a path-prefix rule, not a route rule. The security doc enumerates what remains open even with the key configured: /invocations (described as a 'SageMaker-compatible endpoint (routes to the same inference functions as /v1 endpoints)'), /generative_scoring, /pooling, /classify, /score, /rerank; then the operational controls /pause, /resume, /is_paused, /abort_requests, /scale_elastic_ep, /is_scaling_elastic_ep, /init_weight_transfer_engine, /update_weights, /get_world_size; then utility endpoints /tokenize, /detokenize, /health, /ping, /version, /load. Under VLLM_SERVER_DEV_MODE=1 also /collective_rpc ('Execute arbitrary RPC methods on the engine (extremely dangerous)'), /reset_prefix_cache, /reset_mm_cache, /reset_encoder_cache, /sleep, /wake_up, /is_sleeping and /server_info. The documented consequences are 'Cause denial of service by calling /pause, /scale_elastic_ep, or /abort_requests without a token' and 'Access operational controls to manipulate server state'. The gRPC interface has the same shape with no prefix exception at all: it 'is insecure by default - it does not implement authentication, authorization, or encryption.'
Workaround
Do not rely on --api-key as a security boundary; the docs say so directly ('Do not rely exclusively on --api-key for securing access to vLLM') and prescribe an allowlisting reverse proxy — nginx, Envoy or a Kubernetes Gateway — that 'Explicitly allowlists only the endpoints you want to expose to end users. Blocks all other endpoints, including the unauthenticated inference and operational control endpoints. Implements additional authentication, rate limiting, and logging at the proxy layer.' Never set VLLM_SERVER_DEV_MODE=1 or enable profiler endpoints in production. Keep --grpc-port off unless required and firewall it. Treat endpoint plugins as trusted server code with the same weight as the server itself, because a plugin route 'can shadow a core route and silently replace its behavior' with no conflict enforcement. On the SGLang side, prefer a real admin credential: --admin-api-key marks endpoints admin-only requiring a bearer token. Also firewall the internode surface: KV-cache transfer, torch.distributed and data-parallel channels are unencrypted and unauthenticated by design, and torch.distributed's TCPStore listens on all interfaces.
notes
The authz layer barely exists at the serving layer: vLLM has authentication (one shared API key) and essentially no authorization — no per-tenant identity, no scoping, no policy on which model or adapter a caller may reach. Multi-tenancy is therefore something the routing layer must provide. Where a gateway owns identity, the model server's --api-key is really a shared internal secret and must be treated as such (and note that sgl-router's own probing of /server_info and /model_info requires the same key to be passed as --worker-api-key, so that secret has to be distributed to the routing tier). SCHEME RECLASSIFIED (2026-10-04): was 'config'.
Notes
The authz layer barely exists at the serving layer: vLLM has authentication (one shared API key) and essentially no authorization — no per-tenant identity, no scoping, no policy on which model or adapter a caller may reach. Multi-tenancy is therefore something the routing layer must provide. Where a gateway owns identity, the model server's --api-key is really a shared internal secret and must be treated as such (and note that sgl-router's own probing of /server_info and /model_info requires the same key to be passed as --worker-api-key, so that secret has to be distributed to the routing tier). SCHEME RECLASSIFIED (2026-10-04): was 'config'.