# Symlink following in file operations

Writes, deletes, or extraction that follow symlinks out of the intended directory

_Area: Web injection and code execution. Seen in 7 disclosed reports; 4 confirmed bounties, median $2,256, range $500-$11,250; latest 2026-10-09. Updated 2026-10-23._

## How it works
A file operation trusts a path string, but the filesystem resolves that path through symlinks at the moment of use. If an attacker can plant a symlink (in an archive, a repo, a predictable preview/temp directory, or a mutable container filesystem), a later write, delete, copy, or extract lands outside the intended root. The broken assumption is that "the path I validated is the path I operate on." When the check and the use are separate steps, or the OS re-resolves the path on each syscall, the target can change between them [E2](https://bugbountylibrary.com/r/h1%3A1520931.md)[E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md).

## Where it shows up
- Archive extraction (tar/zip/gem/backup restore) that materializes symlink entries and then writes or deletes through them [E4](https://bugbountylibrary.com/r/h1%3A317321.md)[E5](https://bugbountylibrary.com/r/h1%3A213558.md)
- Path-traversal fixes that validate only the path string, not whether the destination is a symlink [E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md)
- Copy/cleanup into a predictable, attacker-influenceable directory (e.g. `gwd_preview_<name>`) [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)
- Check-then-act on filesystem entries: `lstat`/`is_symlink` followed by a separate open/delete by path [E2](https://bugbountylibrary.com/r/h1%3A1520931.md)
- Cleanup/`rm_rf` running before path-safety validation [E4](https://bugbountylibrary.com/r/h1%3A317321.md)
- Mount or hook loops that resolve paths once at init but re-walk them while the filesystem is still mutable (related TOCTOU variant) [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)

## How to review
Invariant: every write, delete, copy, or extract must stay confined to the intended root even if any path component is a symlink. Enforce this atomically in the syscall (`O_NOFOLLOW`, `openat` with directory fds, `AT_SYMLINK_NOFOLLOW`), not by a prior separate check [E2](https://bugbountylibrary.com/r/h1%3A1520931.md). For extractors, reject or refuse to follow symlink entries, and ensure cleanup/delete ordering cannot precede validation [E4](https://bugbountylibrary.com/r/h1%3A317321.md)[E5](https://bugbountylibrary.com/r/h1%3A213558.md). For repo/API writes, resolve the final target and re-check it is inside the root, then open with no-follow semantics so the re-check is not itself racy; repos legitimately store symlinks [E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md). For mount loops, re-validate paths at use time, not only at init [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md).

Reviewer checklist: does any write/delete/extract path get re-resolved after validation, and is the no-follow guarantee enforced by the syscall?

## Variants seen
- TOCTOU swap of a checked directory for a symlink in `remove_dir_all` [E2](https://bugbountylibrary.com/r/h1%3A1520931.md)
- Symlink bypass of a path-string-only traversal fix in `PutContents` [E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md)
- Archive symlink entry redirecting a later recursive delete before validation [E4](https://bugbountylibrary.com/r/h1%3A317321.md)
- Backup tar symlink to `/etc/passwd` materialized under uploads and served [E5](https://bugbountylibrary.com/r/h1%3A213558.md)
- Predictable preview directory planted with symlinks at many depths [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)
- Container mount loop re-walking mutable paths, escaping to host root [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)

## Why fixes fail
E3's fix validated the path parameter but ignored symlink destinations, so the bypass persisted. E4 shows ordering: validation existed but ran after the destructive operation. E2 shows a documented property ("does not follow symlinks") not enforced atomically, so the guarantee was false. E5 shows no symlink rejection at extract at all.

## Impact and severity
Outcomes ranged from arbitrary file read [E5](https://bugbountylibrary.com/r/h1%3A213558.md) and overwrite/delete [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)[E2](https://bugbountylibrary.com/r/h1%3A1520931.md)[E4](https://bugbountylibrary.com/r/h1%3A317321.md) to RCE [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)[E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md) and full container escape to host [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md). Severity rose where the operation ran privileged or host-side [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)[E2](https://bugbountylibrary.com/r/h1%3A1520931.md), and where the written file was later executed or served [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)[E5](https://bugbountylibrary.com/r/h1%3A213558.md)—RCE in [E1](https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md)[E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md) depends on that downstream execution/serving, not the write alone. Exploitation in the wild at scale raised severity [E3](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md).

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Abalintmagyar-com-articles-google-web-designer-symlink-client-side-rce-cve-2025-1079.md
- E2: https://bugbountylibrary.com/r/h1%3A1520931.md
- E3: https://bugbountylibrary.com/r/blog%3Awiz-io-blog-wiz-research-gogs-cve-2025-8110-rce-exploit.md
- E4: https://bugbountylibrary.com/r/h1%3A317321.md
- E5: https://bugbountylibrary.com/r/h1%3A213558.md
