Threats Tagged 'ghsa-4q9j-6299-gxmr'
View all threats tagged with 'ghsa-4q9j-6299-gxmr'. Filter and sort to focus on specific types of threats.
Stop chasing alerts. Route them.
Start free, then upgrade once to turn Radar into an automated delivery engine for your security stack.
Custom feeds / Automations: email, Slack, webhooks, SIEM/MISP / API access (baseline limits)
API access activates after upgrading in Console -> Billing.
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.
Filter Threats
Narrow down the results by type, severity, or affected countries
Threats Tagged 'ghsa-4q9j-6299-gxmr'
Click on any threat for detailed analysis and mitigation recommendations
0 ### Summary The Dragonfly Manager exposes `GET /api/v1/oauth` and `GET /api/v1/oauth/:id` to unauthenticated clients. The response body deserializes the entire `manager/models.Oauth` struct, which includes the `client_secret` field. Any network-reachable attacker can read the OAuth client secrets configured for `github` or `google` providers, defeating the confidentiality guarantee of those secrets and enabling subsequent abuse against the connected identity providers. ### Affected versions `github.com/dragonflyoss/dragonfly` `<= v2.4.3` (and current `main` at commit `46a8f1e`). The vulnerable wiring is present back to the introduction of OAuth GET handlers and was not addressed by GHSA-j8hf-cp34-g4j7 / CVE-2026-24124, whose remediation only added `jwt + rbac` middleware to the `/jobs` group. ### Privilege required Unauthenticated. The only precondition is that an administrator has registered at least one OAuth provider via `POST /api/v1/oauth` (a one-time setup for tenants that enable GitHub / Google sign-in). ### Vulnerable code [`manager/router/router.go:134-140`](https://github.com/dragonflyoss/dragonfly/blob/e1491bf6134fe307b09e82e11fa94b0587dcd323/manager/router/router.go#L134-L140) (v2.4.3) — the `/oauth` group registration: ```go // Oauth. oa := apiv1.Group("/oauth") oa.POST("", jwt.MiddlewareFunc(), rbac, h.CreateOauth) oa.DELETE(":id", jwt.MiddlewareFunc(), rbac, h.DestroyOauth) oa.PATCH(":id", jwt.MiddlewareFunc(), rbac, h.UpdateOauth) oa.GET(":id", h.GetOauth) oa.GET("", h.GetOauths) ``` Note the asymmetry inside the same `oa` route group: `POST`, `PATCH`, and `DELETE` explicitly attach `jwt.MiddlewareFunc(), rbac` as per-route middleware, but the two `GET` handlers omit both. Compare with the sibling group three lines below at [`manager/router/router.go:143-148`](https://github.com/dragonflyoss/dragonfly/blob/e1491bf6134fe307b09e82e11fa94b0587dcd323/manager/router/router.go#L143-L148), the `/clusters` group: ```go c := apiv1.Group("/clusters", jwt.MiddlewareFunc(), rbac) c.POST("", h.CreateCluster) c.DELETE(":id", h.DestroyCluster) c.PATCH(":id", h.UpdateCluster) c.GET(":id", h.GetCluster) c.GET("", h.GetClusters) ``` Here the middleware pair is attached once at the group level, so every verb on `/clusters` is guarded. The OAuth GETs are an unguarded sibling of the same primitive that GHSA-j8hf-cp34-g4j7 (Jan 2026) patched on the `/jobs` group. This is `sibling-method-dispatch-target` of the AP-012 sub-shape lens: same module, same router file, same anchor primitive ("group lacking JWT + RBAC"), parallel GET methods missed. The handler at [`manager/handlers/oauth.go:127-141`](https://github.com/dragonflyoss/dragonfly/blob/e1491bf6134fe307b09e82e11fa94b0587dcd323/manager/handlers/oauth.go#L127-L141) returns the model directly: ```go func (h *Handlers) GetOauth(ctx *gin.Context) { var params types.OauthParams if err := ctx.ShouldBindUri(¶ms); err != nil { ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()}) return } oauth, err := h.service.GetOauth(ctx.Request.Context(), params.ID) if err != nil { ctx.Error(err) // nolint: errcheck return } ctx.JSON(http.StatusOK, oauth) } ``` [`manager/handlers/oauth.go:155-171`](https://github.com/dragonflyoss/dragonfly/blob/e1491bf6134fe307b09e82e11fa94b0587dcd323/manager/handlers/oauth.go#L155-L171) has the parallel list handler: ```go func (h *Handlers) GetOauths(ctx *gin.Context) { var query types.GetOauthsQuery if err := ctx.ShouldBindQuery(&query); err != nil { ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()}) return } h.setPaginationDefault(&query.Page, &query.PerPage) oauth, count, err := h.service.GetOauths(ctx.Request.Context(), query) if err != nil { ctx.Error(err) // nolint: errcheck return } h.setPaginationLinkHeader(ctx, query.Page, query.PerPage, int(count)) ctx.JSON(http.StatusOK, oauth) } ``` [`manager/models/oauth.go:19-26`](https://github.com/dragonflyoss/dragonfly/blob/e1491bf6134fe307b09e82e11fa94b0587dcd323/manager/models/oauth.go#L19-L26) declares `ClientSecret` with no `json:"-"` tag, so it is serialized into every response: ```go type Oauth struct { BaseModel Name string `gorm:"column:name;type:varchar(256);index:uk_oauth2_name,unique;not null;comment:oauth2 name" json:"name"` BIO string `gorm:"column:bio;type:varchar(1024);comment:biography" json:"bio"` ClientID string `gorm:"column:client_id;type:varchar(256);index:uk_oauth2_client_id,unique;not null;comment:client id for oauth2" json:"client_id"` ClientSecret string `gorm:"column:client_secret;type:varchar(1024);not null;comment:client secret for oauth2" json:"client_secret"` RedirectURL string `gorm:"column:redirect_url;type:varchar(1024);comment:authorization callback url" json:"redirect_url"` } ``` ### How an unauthenticated request reaches the OAuth client_secret 1. `gin.Engine` routes `GET /api/v1/oauth/:id` to the `oa` group registered at [`manager/route Join the discussion | GCVE Database | 07/02/2026, 19:21:30 UTC Added: 07/02/2026, 22:56:58 UTC |
Showing 1 to 1 of 1 result