high

CVE-2026-52799

Go · gogs.io/gogs

Summary

Gogs Missing Authorization in Attachment Download

Severity
high
CVSS
7.5
EPSS
0.4% (p36)
CWE
CWE-639, CWE-862
Also known as
GHSA-p9f5-h3rx-j5qw
Published
2026-06-22
Updated
2026-06-22

Advisory details

Summary

In Gogs 0.14.1, GET /attachments/:uuid returns the raw attachment file without verifying whether the requester has view permission for the associated Issue/Comment/Release or the repository. In a test environment with REQUIRE_SIGNIN_VIEW = false, we confirmed that an unauthenticated user can download attachments belonging to a private repository.

Description

/attachments/:uuid retrieves an attachment record solely by the UUID provided in the URL and returns the corresponding local file without performing any authorization checks against the attachment’s parent object (Issue/Comment/Release) or the repository it belongs to. As a result, even attachments under private repositories can be downloaded by an unauthenticated user (or a user without proper permissions) as long as the UUID is known.

Relevant code (internal/cmd/web.go:306):

m.Get("/attachments/:uuid", func(c *context.Context) {
	attach, err := database.GetAttachmentByUUID(c.Params(":uuid"))
	if err != nil {
		c.NotFoundOrError(err, "get attachment by UUID")
		return
	} else if !com.IsFile(attach.LocalPath()) {
		c.NotFound()
		return
	}

	fr, err := os.Open(attach.LocalPath())
	if err != nil {
		c.Error(err, "open attachment file")
		return
	}
	defer fr.Close()

	c.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
	c.Header().Set("Cache-Control", "public,max-age=86400")
	c.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))

	if _, err = io.Copy(c.Resp, fr); err != nil {
		c.Error(err, "copy from file to response")
		return
	}
})

The UUID lookup itself also performs no validation tied to repository visibility or user permissions. Authorization is not enforced at this layer.

Relevant code (internal/database/attachment.go:124):

// GetAttachmentByUUID returns attachment by given UUID.
func GetAttachmentByUUID(uuid string) (*Attachment, error) {
	return getAttachmentByUUID(x, uuid)
}

Preconditions

Steps to Reproduce

  1. Log in as an administrator and create a private repository, e.g. myadmin/idor-attach-1770724346-1a13bb.
  2. Add an attachment to an Issue in that repository and note the attachment UUID (example UUID used during testing: f06d90f8-5b62-4c10-ac8d-f11fdf870b57).
  3. Log out and access the following as an unauthenticated user:
image image image

Minimum Required Privileges

Impact

References

Related advisories

Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.

Check my repo

Summarize with AI

ChatGPTClaudePerplexity

Sources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.