Miggo Logo

CVE-2025-26625: Git LFS may write to arbitrary files via crafted symlinks

N/A

CVSS Score

Basic Information

EPSS Score
-
Published
10/17/2025
Updated
10/17/2025
KEV Status
No
Technology
TechnologyGo

Technical Details

CVSS Vector
-
Package NameEcosystemVulnerable VersionsFirst Patched Version
github.com/git-lfs/git-lfsgo>= 0.5.2, <= 3.7.03.7.1

Vulnerability Intelligence
Miggo AIMiggo AI

Miggo AIRoot Cause Analysis

The vulnerability in Git LFS (GHSA-6pvw-g552-53c5) allows for arbitrary file writes through crafted symbolic or hard links during git lfs checkout or git lfs pull operations. The root cause is multifaceted and has been addressed across three key commits.

  1. Improper Link Following: The function lfs.GitFilter.SmudgeToFile, responsible for writing file content, originally used os.Create. This function follows symbolic links by default. An attacker could replace a file tracked by LFS with a symbolic link pointing to an arbitrary location on the filesystem, causing Git LFS to write content to that location. The fix replaces os.Create with os.Remove followed by os.OpenFile with the O_EXCL flag, which ensures a new file is created and does not follow existing symlinks, also mitigating a potential TOCTOU race condition.

  2. Path Traversal via Symlinks in Directories: The commands.singleCheckout.Run function, which is central to both checkout and pull, did not validate that each component of the file's path was a directory. An attacker could replace a directory in the path with a symbolic link to another location. The fix introduces a DirWalker utility that uses os.Lstat (which does not follow symlinks) to verify each path component, preventing this traversal.

  3. Bare Repository Execution: The checkout and pull commands could be run in a bare repository (a repository without a working directory). This led to incorrect path resolution, treating repository-relative paths as absolute filesystem paths, potentially leading to writes outside the repository. The commands.checkoutCommand and commands.singleCheckout.Run functions were patched to detect when they are run in a bare repository and prevent the file write operations from proceeding.

The identified vulnerable functions are the key locations where these flaws existed. During exploitation, these functions would be present in the runtime profile as they are directly involved in the vulnerable file I/O operations.

Vulnerable functions

lfs.GitFilter.SmudgeToFile
lfs/gitfilter_smudge.go
The original implementation of `SmudgeToFile` used `os.Create` to write LFS object content. `os.Create` follows symbolic links, which could lead to writing files outside the intended working directory if a malicious symlink is placed in the path. The patch mitigates this by first removing the destination file with `os.Remove` and then creating a new file with `os.OpenFile` using the `O_CREATE|O_EXCL` flags. This ensures that the function does not follow symlinks and also addresses a time-of-check-to-time-of-use (TOCTOU) vulnerability.
commands.singleCheckout.Run
commands/pull.go
This function, used by both `git lfs pull` and `git lfs checkout`, had two vulnerabilities. First, it did not verify if it was running in a valid git working tree, allowing it to be executed in a bare repository which could lead to writing files outside the repository. This was fixed by adding the `hasWorkTree` check. Second, it did not validate the directory path of the file to be checked out, allowing symbolic links to exist in place of directories, which could lead to writing files outside the working tree. This was fixed by introducing `DirWalker` to validate the path components using `os.Lstat`, which does not follow symlinks.
commands.checkoutCommand
commands/command_checkout.go
This is the entry point for the `git lfs checkout` command. It was vulnerable as it could be run in a bare repository, which lacks a working tree. This could lead to files being written outside the repository due to incorrect path handling. The patch adds a check to ensure that the command is executed within a git working tree.

WAF Protection Rules

WAF Rule

### Imp**t W**n popul*tin* * *it r*pository's workin* tr** wit* t** *ont*nts o* *it L*S o*j**ts, **rt*in *it L*S *omm*n*s m*y writ* to *il*s visi*l* outsi** t** *urr*nt *it workin* tr** i* sym*oli* or **r* links *xist w*i** *olli** wit* t** p*t*s o*

Reasoning

T** vuln*r**ility in *it L*S (**S*-*pvw-****-****) *llows *or *r*itr*ry *il* writ*s t*rou** *r**t** sym*oli* or **r* links *urin* `*it l*s ****kout` or `*it l*s pull` op*r*tions. T** root **us* is multi****t** *n* **s ***n ***r*ss** **ross t*r** k*y