GHSA-rj4g-rqgh-rx9h: Github.com/lin snow/Ech0 Ech0 Comment Model's Email Field Vulnerability

MODERATE
CVSS 5.3
CWE-200 CWE-359
Published
Advisory Summary

GHSA-rj4g-rqgh-rx9h is a MODERATE (CVSS 5.3) ech0 comment model's email field vulnerability (CWE-200: Exposure of Sensitive Information to an Unauthorized Actor) affecting Github.com/lin snow/Ech0 libraries in the Go ecosystem. The issue involves ech0 comment model's email field returned on public /api/comments endpoints. Remediation is available by upgrading affected packages to version 1.4.8-0.20260503034700-cb8d7a997dd8.

GHSA-rj4g-rqgh-rx9h at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-rj4g-rqgh-rx9h
Severity MODERATE
CVSS v3.1 Base Score 5.3
CWE Classification CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
Affected Product Github.com/lin snow/Ech0
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 5.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity None (I:N)
Availability None (A:N)

How to Fix GHSA-rj4g-rqgh-rx9h

To remediate this vulnerability, upgrade all affected Github.com/lin snow/Ech0 dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/lin-snow/Ech0 fixed: 1.4.8-0.20260503034700-cb8d7a997dd8
Upgrade github.com/lin-snow/Ech0 to 1.4.8-0.20260503034700-cb8d7a997dd8
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/lin-snow/Ech0

How to Check if You Are Affected

To determine whether your application is affected by GHSA-rj4g-rqgh-rx9h, inspect your project dependencies for Github.com/lin snow/Ech0:

inspect dependencies for github.com/lin-snow/Ech0

Analyze the terminal output to locate any version of Github.com/lin snow/Ech0 in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.4.8-0.20260503034700-cb8d7a997dd8), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor, where the product exposes sensitive information to an actor that is not explicitly authorized to have access to that information. In Github.com/lin snow/Ech0, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## 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`: ```go 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: ```go 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: ```python 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='leaked-harvest-target@example.com' 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 comment on the topics the site covers. No authentication required. No admin role required. The `/comments/public` endpoint returns cross-echo aggregated data, so one call covers the whole instance. ## Recommended Fix Change the JSON tag on the Email field to match the adjacent PII fields: ```go Email string `gorm:"size:255;not null;index" json:"-"` ``` Or, if some authenticated view needs the email, introduce a `PublicComment` DTO that projects only non-sensitive fields: ```go type PublicComment struct { ID string `json:"id"` EchoID string `json:"echo_id"` Nickname string `json:"nickname"` Website string `json:"website,omitempty"` Content string `json:"content"` Status string `json:"status"` Hot bool `json:"hot"` Source string `json:"source"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } ``` Project the handler output through this DTO. Keep the raw `Comment` struct internal to the service layer. --- *Found by [aisafe.io](https://aisafe.io)*

GHSA-rj4g-rqgh-rx9h Affected Github.com/lin snow/Ech0 Versions

1 component(s)
Fixed Versions:
1.4.8-0.20260503034700-cb8d7a997dd8
Product / Package Ecosystem Affected Versions Fixed Version
github.com/lin-snow/Ech0
Go
< 1.4.8-0.20260503034700-cb8d7a997dd8
1.4.8-0.20260503034700-cb8d7a997dd8

References

Frequently Asked Questions

What is GHSA-rj4g-rqgh-rx9h?
GHSA-rj4g-rqgh-rx9h is a security vulnerability in Github.com/lin snow/Ech0 involving Ech0 comment model's Email field returned on public /api/comments endpoints under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor.
Which Github.com/lin snow/Ech0 versions are affected?
Affected versions include releases prior to 1.4.8-0.20260503034700-cb8d7a997dd8 across affected packages: github.com/lin-snow/Ech0.
What version fixes GHSA-rj4g-rqgh-rx9h?
Upgrading to 1.4.8-0.20260503034700-cb8d7a997dd8 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/lin-snow/Ech0 affected?
Yes, github.com/lin-snow/Ech0 is affected in releases prior to 1.4.8-0.20260503034700-cb8d7a997dd8. Upgrade your dependency to 1.4.8-0.20260503034700-cb8d7a997dd8 or later.
What is the CVSS score of GHSA-rj4g-rqgh-rx9h?
GHSA-rj4g-rqgh-rx9h has a CVSS v3.1 base score of 5.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N.
What CWE is associated with GHSA-rj4g-rqgh-rx9h?
GHSA-rj4g-rqgh-rx9h is classified under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor (The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.).
How can I check Go dependencies for GHSA-rj4g-rqgh-rx9h?
Run the dependency tree command: 'inspect dependencies for github.com/lin-snow/Ech0'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-rj4g-rqgh-rx9h",
  "modified" : "2026-05-07T21:16:15Z",
  "published" : "2026-05-07T21:16:15Z",
  "aliases" : [ ],
  "summary" : "Ech0 comment model's Email field returned on public /api/comments endpoints",
  "details" : "## Summary\n\nThe `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.\n\n## Details\n\nThe Comment model at `internal/model/comment/comment.go:33`:\n\n```go\ntype Comment struct {\n    // ... \n    Email     string     `gorm:\"size:255;not null;index\" json:\"email\"`\n    IPHash    string     `gorm:\"size:128;index\"          json:\"-\"`\n    UserAgent string     `gorm:\"size:512\"                json:\"-\"`\n    // ...\n}\n```\n\nThe `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.\n\nRoutes at `internal/router/comment.go:20` and comment public-feed route:\n\n```go\nappRouterGroup.PublicRouterGroup.GET(\"/comments\", middleware.NoCache(), h.CommentHandler.ListCommentsByEchoID())\nappRouterGroup.PublicRouterGroup.GET(\"/comments/public\", middleware.NoCache(), h.CommentHandler.ListPublicComments())\n```\n\nBoth 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.\n\nThe 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.\n\nGHSA-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).\n\n## Proof of Concept\n\nAnonymous caller harvests commenter emails on the default install:\n\n```python\nimport requests\nTARGET = \"http://localhost:8300\"\n\n# Any echo UUID from the public feed.\npub_id = requests.get(f\"{TARGET}/api/echo/page?page=1&pageSize=1\").json()[\"data\"][\"items\"][0][\"id\"]\n\n# No auth header. The response includes the raw email field.\nr = requests.get(f\"{TARGET}/api/comments\", params={\"echo_id\": pub_id})\nfor c in r.json()[\"data\"]:\n    print(f\"  nickname={c['nickname']!r}  email={c.get('email')!r}\")\n\n# The /public variant returns recent comments across every echo.\nr = requests.get(f\"{TARGET}/api/comments/public\", params={\"limit\": 100})\nemails = {c.get(\"email\") for c in r.json()[\"data\"] if c.get(\"email\")}\nprint(f\"harvested {len(emails)} unique emails from /comments/public\")\n```\n\nObserved on v4.5.6:\n\n```\nnickname='GuestHarvestMe'  email='leaked-harvest-target@example.com'\nharvested 1 unique emails from /comments/public\n```\n\nThe instance had one guest comment; its email returned in both endpoints. An instance with any commenter volume returns every address.\n\n## Impact\n\nAnonymous 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:\n\n- **GDPR and CCPA.** Email is personal data. Exposing it to any internet visitor without consent is a notifiable incident under both regimes.\n- **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.\n- **Cross-instance aggregation.** A scraper against any public-facing Ech0 instance yields a curated list of people who comment on the topics the site covers.\n\nNo authentication required. No admin role required. The `/comments/public` endpoint returns cross-echo aggregated data, so one call covers the whole instance.\n\n## Recommended Fix\n\nChange the JSON tag on the Email field to match the adjacent PII fields:\n\n```go\nEmail string `gorm:\"size:255;not null;index\" json:\"-\"`\n```\n\nOr, if some authenticated view needs the email, introduce a `PublicComment` DTO that projects only non-sensitive fields:\n\n```go\ntype PublicComment struct {\n    ID        string    `json:\"id\"`\n    EchoID    string    `json:\"echo_id\"`\n    Nickname  string    `json:\"nickname\"`\n    Website   string    `json:\"website,omitempty\"`\n    Content   string    `json:\"content\"`\n    Status    string    `json:\"status\"`\n    Hot       bool      `json:\"hot\"`\n    Source    string    `json:\"source\"`\n    CreatedAt int64     `json:\"created_at\"`\n    UpdatedAt int64     `json:\"updated_at\"`\n}\n```\n\nProject the handler output through this DTO. Keep the raw `Comment` struct internal to the service layer.\n\n---\n*Found by [aisafe.io](https://aisafe.io)*",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/lin-snow/Ech0"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.4.8-0.20260503034700-cb8d7a997dd8"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/lin-snow/Ech0/security/advisories/GHSA-rj4g-rqgh-rx9h"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/lin-snow/Ech0/commit/cb8d7a997dd8f573ef0e22e4e6b23b2b8ee92ebd"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/lin-snow/Ech0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-359" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-07T21:16:15Z",
    "nvd_published_at" : null
  }
}