Ech0: Unauthenticated SSRF in GetWebsiteTitle allows access to internal services and cloud metadata
Date: 2026-04
Affected: go/github.com/lin-snow/ech0
Attack vector: ssrf
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-35037
CWE: CWE-918
CVSS: 7.2 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N)

## Summary The `GET /api/website/title` endpoint accepts an arbitrary URL via the `website_url` query parameter and makes a server-side HTTP request to it without any validation of the target host or IP address. The endpoint requires no authentication. An attacker can use this to reach internal network services, cloud metadata endpoints (169.254.169.254), and localhost-bound services, with partial response data exfiltrated via the HTML `<title>` tag extraction. ## Details The vulnerability exists in the interaction between four components: **1. Route registration — no authentication** (`internal/router/common.go:11`): ```go appRouterGroup.PublicRouterGroup.GET("/website/title", h.CommonHandler.GetWebsiteTitle()) ``` The `PublicRouterGroup` is created at `internal/router/router.go:34` as `r.Group("/api")` with no auth middleware attached (unlike `AuthRouterGroup` which uses `JWTAuthMiddleware`). **2. Handler — no input validation** (`internal/handler/common/common.go:106-127`): ```go func (commonHandler *CommonHandler) GetWebsiteTitle() gin.HandlerFunc { return res.Execute(func(ctx *gin.Context) res.Response { var dto commonModel.GetWebsiteTitleDto if err := ctx.ShouldBindQuery(&dto); err != nil { ... } title, err := commonHandler.commonService.GetWebsiteTitle(dto.WebSiteURL) ... }) } ``` The DTO (`internal/model/common/common_dto.go:155-156`) only enforces `binding:"required"` — no URL scheme or host validation. **3. Service — Tri


Mitigations:

Architectural layers (MAESTRO):