CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

CVE-2026-52811

criticalcovered by 1 sourcefirst seen 2026-06-23
Summary (*Repository).UploadRepoFiles checks for symlinks only on the leaf of the upload target (osx.IsSymlink(targetPath)). The siblings UpdateRepoFile, DeleteRepoFile, and GetDiffPreview use hasSymlinkInPath, which lstats every component — UploadRepoFiles is the lone outlier. An attacker with repo-write access plus a multipart upload whose filename contains a literal backslash (preserved by filepath.Base on Linux, then converted to / by pathx.Clean) redirects the write through a previously-committed directory symlink. iox.CopyFile opens the destination with os.Create (no O_NOFOLLOW), so the kernel follows the parent symlink and writes attacker bytes anywhere the gogs UID can write — ~git/.ssh/authorized_keys → SSH foothold, or <repo>.git/hooks/post-receive → next-push RCE. Windows builds are unaffected: filepath.Base treats \ as a separator (strips the multi-segment trick) and git defaults core.symlinks=false at checkout (committed mode-120000 entries become text files, not real symlinks). Details The asymmetric check at internal/database/repo_editor.go:601-612: targetPath := path.Join(dirPath, upload.Name) if osx.IsSymlink(targetPath) { // ← LEAF-ONLY return errors.Newf("cannot overwrite symbolic link: %s", upload.Name) } if err = iox.CopyFile(tmpPath, targetPath); err != nil { ... } vs. UpdateRepoFile's correct walker at internal/database/repo_editor.go:163: if hasSymlinkInPath(localPath, opts.OldTreeName) || hasSymlinkInPath(localPath, opts.NewTreeName) { return errors.New("cannot update file with symbolic link in path") } hasSymlinkInPath (internal/database/repo_editor.go:120-131) lstats every component; osx.IsSymlink (internal/osx/osx.go:35-41) is os.Lstat mode-bit on the leaf — fine inside the loop, wrong as a single call. Multi-segment upload.Name reaches the loop because: (1) c.Req.FormFile("file") returns *multipart.FileHeader whose Filename is filepath.Base(filename) — Linux only treats / as separator, so backslashes are preserved; (2) NewUpload

⚡ Watch CVE-2026-52811

Get an email if CVE-2026-52811 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.

Exploitation outlook

Advisory coverage (1)

External references

NVD record for CVE-2026-52811

CVE.org record

Embed the live status

CVE-2026-52811 live status badge — this badge updates automatically when the KEV or exploit status changes. How to embed it →

[![CVE-2026-52811 status](https://www.csirts.com/badge/CVE-2026-52811)](https://www.csirts.com/cve/CVE-2026-52811)