python-dotenv: Symlink following in set_key allows arbitrary file overwrite via cross-device rename fallback
Date: 2026-04
Affected: pip/python-dotenv
Attack vector: path-traversal
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-28684
CWE: CWE-59
CWE-61
CVSS: 6.6 (CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H)

### Summary `set_key()` and `unset_key()` in python-dotenv follow symbolic links when rewriting `.env` files, allowing a local attacker to overwrite arbitrary files via a crafted symlink when a cross-device rename fallback is triggered. ### Details The `rewrite()` context manager in `dotenv/main.py` is used by both `set_key()` and `unset_key()` to safely modify `.env` files. It works by writing to a temporary file (created in the system's default temp directory, typically `/tmp`) and then using `shutil.move()` to replace the original file. When the `.env` path is a symbolic link and the temp directory resides on a different filesystem than the target (a common configuration on Linux systems using tmpfs for `/tmp`), the following sequence occurs: 1. `shutil.move()` first attempts `os.rename()`, which fails with an `OSError` because atomic renames cannot cross device boundaries. 2. On failure, `shutil.move()` falls back to `shutil.copy2()` followed by `os.unlink()`. 3. `shutil.copy2()` calls `shutil.copyfile()` with `follow_symlinks=True` by default. 4. This causes the content to be written to the **symlink target** rather than replacing the symlink itself. An attacker who has write access to the directory containing a `.env` file can pre-place a symlink pointing to any file that the application process has write access to. When the application (or a privileged process such as a deploy script, Docker entrypoint, or CI pipeline) calls `set_key()` or `unset_key()`, the sym


Mitigations:

Architectural layers (MAESTRO):