GHSA-5fqm-cc34-fcf5 Cosmos-Server's constellation public-devices endpoint accepts arbitrary bearer tokens
Summary`GET /cosmos/api/constellation/public-devices` discloses Constellation device metadata to a requester that supplies any non-empty `Authorization` header. The handler strips the string `Bearer ` from the header but never validates the resulting token and never uses it in the database query.This was confirmed locally by routing a request through the real `tokenMiddleware` with `Authorization: Bearer not-a-real-token`. The request returned public Constellation device metadata from a disposable fixture. A missing-header negative control returned `401 Unauthorized`, proving the bypass is specifically the acceptance of arbitrary bearer values.DetailsSource-to-sink path:`src/httpServer.go:690` registers `/api/constellation/public-devices` on the authenticated admin API router.`src/httpServer.go:815-817` applies `SecureAPI(..., public=false, ...)`, which runs `tokenMiddleware`.`src/httpServer.go:231-237` only treats `Authorization: Bearer cosmos_...` as a Cosmos API token for validation. Other bearer strings are not validated by the middleware and fall through to the handler.`src/constellation/api_devices_public.go:42-47` checks only that the `Authorization` header is present.`src/constellation/api_devices_public.go:49-50` strips `Bearer ` but does not verify the token or compare it with a device/API key.`src/constellation/api_devices_public.go:63-67` queries all non-blocked and non-invisible devices without including the stripped auth value in the filter.`src/constellation/api_devices_public.go:84-99` returns device names, user nicknames, cleaned VPN/internal IPs, role flags, public hostname, and port.The handler does not call `utils.CheckPermissions`, `utils.CheckPermissionsOrSelf`, the Cosmos API-token permission check, or any Constellation-token validation before returning the data.Default/common exposure evidence:The route is registered in the standard server setup (`src/httpServer.go:690`).Constellation is a documented product feature described as the VPN used to securely access applications remotely (`readme.md:49`).The default config ships Constellation disabled (`src/utils/utils.go:104-105`), so impact requires a deployment that enables the Constellation/VPN feature and has at least one non-blocked, non-invisible device.The root package identifies the product as `cosmos-server` version `0.22.18` (`package.json:1-2`).The Go module is `github.com/azukaar/cosmos-server` (`go.mod:0`).False-positive screen:The PoC wraps the handler in the same `tokenMiddleware` used by `SecureAPI`, so it tests the deployed middleware behavior rather than directly calling the handler alone.A request with no `Authorization` header returns `401 Unauthorized`.A request with `Authorization: Bearer not-a-real-token` returns `200 OK` and device metadata.The fixture data is stored in a disposable embedded database under `t.TempDir()` and no external services are contacted.The route is not protected by handler-level `CheckPermissions`, and the arbitrary bearer value is not used by the database query.Candidate score: 13/18. Reachability 1, attacker control 2, privilege required 2, sink impact 1, mitigation weakness 2, default exposure 1, safe PoC feasibility 2, static certainty 2, false-positive resistance 2. The lower score reflects that Constellation is disabled in the shipped default config, but it is a documented/common product feature.Exploitability gate: confirmed for deployments with Constellation enabled and populated with devices. The reachable source, arbitrary-token bypass, data-disclosure impact, safe local reproduction, and affected-version evidence are present. Default exposure is feature-dependent rather than enabled in a fresh default config.PoCClean-checkout maintainer recipe:Check out commit `88de73dcca50172393a75de0e4dc3ab93622825c` or version `0.22.18`.Create `src/zz_security_poc_test.go` with the following test.Run `go test ./src -run TestAuditPublicDevicesAllowsArbitraryBearer -count=1 -v`.Delete `src/zz_security_poc_test.go` after confirming.Observed output in this environment:Control/negative case: the same test first sends the request without `Authorization` and expects `401 Unauthorized`. The subsequent `Authorization: Bearer not-a-real-token` request succeeds and returns the fixture, proving the bypass is not an intentionally unauthenticated endpoint but an unvalidated-header check.ImpactAn unauthenticated network attacker can enumerate Constellation device metadata from deployments that enable the Constellation/VPN feature and have visible devices. The response exposes device names, user nicknames, internal/VPN IP addresses, node roles such as lighthouse/relay/exit-node flags, public hostnames, and ports. This information can reveal private network topology and user/device inventory and can support targeted follow-on attacks against the VPN or exposed nodes.The issue does not require a valid Cosmos session, valid Cosmos API token, valid Constellation token, or user interaction; any arbitrary non-empty bearer string is accepted.Suggested remediationReplace the header-presence check with real authorization. Depending on the intended trust model, the handler should require one of:a valid Cosmos user/API token with an appropriate permission such as `PERM_RESOURCES_READ` or `PERM_CONFIGURATION_READ`, ora dedicated Constellation device/API token that is cryptographically verified and used to scope the query to devices the caller is allowed to see.Also add regression tests for:missing `Authorization` header returns 401,malformed/arbitrary bearer token returns 401,invalid `cosmos_` API token returns 401 through middleware,valid but underprivileged token is rejected,valid authorized token returns only permitted devices.CreditsThai Son Dinh from VinSOC Labs (R&D)Nguyen Huy Vu Dung from VinSOC Labs (AppSec)
CVSS v3.1 score: 5.3