Portainer Has an Arbitrary File Read via Git Symlink Injection in Stack Auto-Update
Portainer supports deploying stacks from Git repositories. When a Git-backed stack is created or updated, Portainer clones the repository using go-git v5, which translates Git blob entries with mode 0o120000 (symlink) into real OS symlinks on the host filesystem via os.Symlink. The only entry blocked from becoming a symlink is .gitmodules; every other path — including docker-compose.yml, which Portainer treats as the stack entry point — is created as a symlink without validation.
Portainer's GET /api/stacks/{id}/file endpoint then reads the stack entry point with os.ReadFile, which follows OS symlinks transparently. A repository containing docker-compose.yml as a symlink to an arbitrary filesystem path (for example /etc/passwd or a mounted Kubernetes service account token) causes the symlink target's contents to be returned verbatim in the HTTP response. Any authenticated user with rights to create or update a Git-backed stack — the default configuration in Portainer CE — can read arbitrary files accessible to the Portainer process.
The issue is amplified by Git-stack auto-update: an attacker can create a stack from a legitimate repository, pass initial review, and later push a commit that replaces docker-compose.yml with a symlink; the file read is then triggered on the next scheduled update cycle with no further interaction required.
High
Attack complexity is Low: the attacker needs only the ability to host a Git repository and the default-granted permission to create a Git-backed stack. Privilege required is Low in typical CE deployments, where non-admin users can manage their own stacks; administrators retain the same attack surface regardless of the setting. Impact on confidentiality is High — the Portainer process commonly runs as root (required for Docker socket access), so arbitrary file read includes /etc/shadow, Kubernetes service account tokens, Docker secrets, environment variables, and the Portainer database itself. Integrity and availability are not directly affected, but the leaked contents (service account tokens, registry credentials, database session keys) frequently enable onward compromise of the host and managed environments.
The vulnerability exists in every Portainer release since the introduction of Git-based stack deployment support — Git-backed stacks have always performed an unrestricted go-git checkout and subsequently read the entry-point file through os.ReadFile without resolving symlinks.
Fixes are included in the following releases:
| Branch | First vulnerable | Fixed in |
|--------------|------------------|------------|
| 2.33.x (LTS) | 2.33.0 | 2.33.8 |
| 2.39.x (LTS) | 2.39.0 | 2.39.2 |
| 2.40.x (STS) | all prior | 2.41.0 |
Portainer releases prior to 2.33.0 are end-of-life and will not receive a fix. Users on EOL versions should upgrade to a supported LTS branch.
Administrators who cannot immediately upgrade can reduce exposure by:
/data/compose/ (or your configured data directory) for symlink entries — find /data/compose -type l — and treat any unexpected results as potential evidence of past exploitation.None of these replace the fix.
The vulnerability is the combination of two primitives. go-git translates Git symlink entries into OS symlinks unconditionally (except .gitmodules):
```go
// go-git v5 — Worktree.checkoutFileSymlink
func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) {
if strings.EqualFold(f.Name, gitmodulesFile) {
return ErrGitModulesSymlink
}
// ... reads blob content as raw bytes ...
err = w.Filesystem.Symlink(string(bytes), f.Name)
return
}
```
Relative symlink targets (../../etc/passwd) are passed through to os.Symlink as-is and escape the worktree at OS resolution time. (Absolute targets are chrooted to the worktree by go-billy's ChrootHelper.Symlink and are not useful to the attacker.)
On the read side, GetFileContent in `api/filesystem/filesys
This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality high, integrity high, availability high.
The score comes from this vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
CVE-2026-44881 is classified as CWE-200: Exposure of Sensitive Information. Information that should stay internal is disclosed to someone who is not authorised to see it.
CVE-2026-44881 is recorded against 2 packages.
Published on 14 May 2026 and last revised on 25 June 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.
github.com (Web)
nvd.nist.gov (Advisory)
github.com (Package)
github.com (Web)
github.com (Web)
github.com (Web)
github.com/portainer/portainer has other advisories on record. If you are patching this one, these are worth checking on the same host:
These advisories are the same class of weakness (CWE-200: Exposure of Sensitive Information) in other software:
Details
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| github.com/portainer/portainer | — | — |
| portainer | — | — |
References
Similar Threats
Exploit Protection
CVE-2026-44881 carries CVSS 9.9 Critical rating. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For CVE-2026-44881 →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.
Stay up to date with the latest from Boteraser.
We use cookies to improve your experience on our site. By using our site, you consent to cookies.
Manage your cookie preferences below:
Essential cookies enable basic functions and are necessary for the proper function of the website.
CloudFlare provides web performance and security solutions, enhancing site speed and protecting against threats.
Service URL: developers.cloudflare.com (opens in a new window)
These cookies are needed for adding comments on this website.
These cookies are used for managing login functionality on this website.
Statistics cookies collect information anonymously. This information helps us understand how visitors use our website.
Google Analytics is a powerful tool that tracks and analyzes website traffic for informed marketing decisions.
Service URL: policies.google.com (opens in a new window)
You can find more information in our Cookie Policy and Privacy Policy.