GHSA-JJ5M-H57J-5GV7

Vulnerability from github – Published: 2026-02-17 18:40 – Updated: 2026-02-19 21:14
VLAI?
Summary
Gogs Allows Cross-Repository Comment Deletion via DeleteComment
Details

IDOR: Cross-Repository Comment Deletion via DeleteComment

Summary

The POST /:owner/:repo/issues/comments/:id/delete endpoint does not verify that the comment belongs to the repository specified in the URL. This allows a repository administrator to delete comments from any other repository by supplying arbitrary comment IDs, bypassing authorization controls.

Vulnerability Details

Field Value
Affected File internal/route/repo/issue.go
Affected Function DeleteComment (lines 955-968)
Secondary File internal/database/comment.go
Secondary Function DeleteCommentByID (lines 505-520)

Root Cause

The vulnerability exists due to insufficient authorization validation in the comment deletion flow:

1. Missing Repository Ownership Check in DeleteComment

In internal/route/repo/issue.go, the function retrieves a comment by ID without verifying repository ownership:

func DeleteComment(c *context.Context) {
    comment, err := database.GetCommentByID(c.ParamsInt64(":id"))
    if err != nil {
        c.NotFoundOrError(err, "get comment by ID")
        return
    }

    // Only checks if user is comment poster OR admin of the CURRENT repo (from URL)
    if c.UserID() != comment.PosterID && !c.Repo.IsAdmin() {
        c.NotFound()
        return
    } else if comment.Type != database.CommentTypeComment {
        c.Status(http.StatusNoContent)
        return
    }

    // No verification that comment.IssueID belongs to c.Repo.Repository.ID!
    if err = database.DeleteCommentByID(c.User, comment.ID); err != nil {
        c.Error(err, "delete comment by ID")
        return
    }

    c.Status(http.StatusOK)
}

2. Database Layer Performs No Authorization

In internal/database/comment.go, the deletion function performs no repository validation:

func DeleteCommentByID(doer *User, id int64) error {
    comment, err := GetCommentByID(id)
    if err != nil {
        if IsErrCommentNotExist(err) {
            return nil
        }
        return err
    }

    // Directly deletes without checking repository ownership
    sess := x.NewSession()
    defer sess.Close()
    if err = sess.Begin(); err != nil {
        return err
    }

    if _, err = sess.ID(comment.ID).Delete(new(Comment)); err != nil {
        // ...
    }
    // ...
}

Proof of Concept

Prerequisites

  1. Two users: Alice (attacker) and Bob (victim)
  2. Alice is admin of alice/attacker-repo
  3. Bob has created an issue with a comment on bob/victim-repo
  4. Attacker needs to obtain the comment ID from victim's repository (e.g., ID: 42)

HTTP Request

POST /alice/attacker-repo/issues/comments/42/delete HTTP/1.1
Host: gogs.example.com
Cookie: i_like_gogs=<alice_session_token>

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.13.4"
      },
      "package": {
        "ecosystem": "Go",
        "name": "gogs.io/gogs"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.14.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-25120"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-02-17T18:40:44Z",
    "nvd_published_at": "2026-02-19T07:17:45Z",
    "severity": "MODERATE"
  },
  "details": "# IDOR: Cross-Repository Comment Deletion via DeleteComment\n\n## Summary\n\nThe `POST /:owner/:repo/issues/comments/:id/delete` endpoint does not verify that the comment belongs to the repository specified in the URL. This allows a repository administrator to delete comments from any other repository by supplying arbitrary comment IDs, bypassing authorization controls.\n\n## Vulnerability Details\n\n| Field | Value |\n|-------|-------|\n| Affected File | `internal/route/repo/issue.go` |\n| Affected Function | `DeleteComment` (lines 955-968) |\n| Secondary File | `internal/database/comment.go` |\n| Secondary Function | `DeleteCommentByID` (lines 505-520) |\n\n## Root Cause\n\nThe vulnerability exists due to insufficient authorization validation in the comment deletion flow:\n\n### 1. Missing Repository Ownership Check in DeleteComment\n\nIn `internal/route/repo/issue.go`, the function retrieves a comment by ID without verifying repository ownership:\n\n```go\nfunc DeleteComment(c *context.Context) {\n    comment, err := database.GetCommentByID(c.ParamsInt64(\":id\"))\n    if err != nil {\n        c.NotFoundOrError(err, \"get comment by ID\")\n        return\n    }\n\n    // Only checks if user is comment poster OR admin of the CURRENT repo (from URL)\n    if c.UserID() != comment.PosterID \u0026\u0026 !c.Repo.IsAdmin() {\n        c.NotFound()\n        return\n    } else if comment.Type != database.CommentTypeComment {\n        c.Status(http.StatusNoContent)\n        return\n    }\n\n    // No verification that comment.IssueID belongs to c.Repo.Repository.ID!\n    if err = database.DeleteCommentByID(c.User, comment.ID); err != nil {\n        c.Error(err, \"delete comment by ID\")\n        return\n    }\n\n    c.Status(http.StatusOK)\n}\n```\n\n### 2. Database Layer Performs No Authorization\n\nIn `internal/database/comment.go`, the deletion function performs no repository validation:\n\n```go\nfunc DeleteCommentByID(doer *User, id int64) error {\n    comment, err := GetCommentByID(id)\n    if err != nil {\n        if IsErrCommentNotExist(err) {\n            return nil\n        }\n        return err\n    }\n\n    // Directly deletes without checking repository ownership\n    sess := x.NewSession()\n    defer sess.Close()\n    if err = sess.Begin(); err != nil {\n        return err\n    }\n\n    if _, err = sess.ID(comment.ID).Delete(new(Comment)); err != nil {\n        // ...\n    }\n    // ...\n}\n```\n\n## Proof of Concept\n\n### Prerequisites\n\n1. Two users: **Alice** (attacker) and **Bob** (victim)\n2. Alice is admin of `alice/attacker-repo`\n3. Bob has created an issue with a comment on `bob/victim-repo`\n4. Attacker needs to obtain the comment ID from victim\u0027s repository (e.g., ID: 42)\n\n### HTTP Request\n\n```http\nPOST /alice/attacker-repo/issues/comments/42/delete HTTP/1.1\nHost: gogs.example.com\nCookie: i_like_gogs=\u003calice_session_token\u003e\n\n```",
  "id": "GHSA-jj5m-h57j-5gv7",
  "modified": "2026-02-19T21:14:32Z",
  "published": "2026-02-17T18:40:44Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/gogs/gogs/security/advisories/GHSA-jj5m-h57j-5gv7"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25120"
    },
    {
      "type": "WEB",
      "url": "https://github.com/gogs/gogs/commit/1b226ca48dc8b3e95cc1c41229d72819c960a1b7"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/gogs/gogs"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Gogs Allows Cross-Repository Comment Deletion via DeleteComment"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…