Every CVE Search/ Get API key

CVE-2026-28684

python-dotenv: Symlink following in set_key allows arbitrary file overwrite via cross-device rename fallback

6.6 MediumFix available

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
Low
User interaction
Required

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
High

Exploit likelihood

0.25%Up 0.2 points since Apr 21, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.6

python-dotenv: Symlink following in set_key allows arbitrary file overwrite via cross-device rename fallback

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
CVE-2026-28684
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Weakness
CWE-59, CWE-61
Updated
2026-11-02
EUVDEUVD-2026-23901 6.6

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
EUVD-2026-23901
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-mf9w-mj56-hr94 6.6

python-dotenv: Symlink following in set_key allows arbitrary file overwrite via cross-device rename fallback

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 symlink target is overwritten with the new .env content.

This vulnerability does not require a race condition and is fully deterministic once the preconditions are met.

Impact

The primary impacts are to integrity and availability:

  • File overwrite / destruction (DoS): An attacker can cause an application or privileged process to corrupt or destroy configuration files, database configs, or other sensitive files it would not normally have access to modify.
  • Integrity violation: The target file's original content is replaced with .env-formatted content controlled by the attacker.
  • Potential privilege escalation: In scenarios where a privileged process (running as root or a service account) calls set_key(), the attacker can leverage this to write to files beyond their own access level.

The scope of impact depends on the application using python-dotenv and the privileges under which it runs.

Proof of Concept

The following script demonstrates the vulnerability. It requires /tmp and the user's home directory to reside on different devices (common on systemd-based Linux systems with tmpfs).

import os
import sys
import tempfile
from dotenv import set_key

# Pre-condition: /tmp must be on a different device than the target directory.
tmp_dev = os.stat("/tmp").st_dev
home_dev = os.stat(os.path.expanduser("~")).st_dev
assert tmp_dev != home_dev, "Skipped: /tmp and ~ are on the same device (no cross-device move)"

with tempfile.TemporaryDirectory(dir=os.path.expanduser("~")) as workdir:
    # File an attacker wants to overwrite
    target = os.path.join(workdir, "victim_config.txt")
    with open(target, "w") as f:
        f.write("DB_PASSWORD=supersecret\n")

    # Attacker pre-places a symlink at the path the application will use as .env
    env_symlink = os.path.join(workdir, ".env")
    os.symlink(target, env_symlink)

    before = open(target).read()

    # Application writes a new key -- triggers the cross-device fallback
    set_key(env_symlink, "INJECTED", "attacker_value")

    after = open(target).read()

    print("Before:", repr(before))
    print("After: ", repr(after))
    print("Symlink target overwritten:", target)

Expected output:

Before: 'DB_PASSWORD=supersecret\n'
After:  "DB_PASSWORD=supersecret\nINJECTED='attacker_value'\n"
Symlink target overwritten: /home/user/tmp806nut2g/victim_config.txt

Remediation

The fix changes the rewrite() context manager in the following ways:…

Record
GHSA-mf9w-mj56-hr94
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Weakness
CWE-59, CWE-61
Updated
2026-11-02
NVD 6.6

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
CVE-2026-28684
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Weakness
CWE-59, CWE-61
Updated
2026-11-02
OSV 6.6

python-dotenv: Symlink following in set_key allows arbitrary file overwrite via cross-device rename fallback

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
CVE-2026-28684
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Weakness
CWE-59, CWE-61
Updated
2026-11-02
OSVDEBIAN-CVE-2026-28684 6.6

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
DEBIAN-CVE-2026-28684
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
Show 10 moreShow less
OSVGHSA-mf9w-mj56-hr94 6.6

python-dotenv: Symlink following in set_key allows arbitrary file overwrite via cross-device rename fallback

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 symlink target is overwritten with the new .env content.

This vulnerability does not require a race condition and is fully deterministic once the preconditions are met.

Impact

The primary impacts are to integrity and availability:

  • File overwrite / destruction (DoS): An attacker can cause an application or privileged process to corrupt or destroy configuration files, database configs, or other sensitive files it would not normally have access to modify.
  • Integrity violation: The target file's original content is replaced with .env-formatted content controlled by the attacker.
  • Potential privilege escalation: In scenarios where a privileged process (running as root or a service account) calls set_key(), the attacker can leverage this to write to files beyond their own access level.

The scope of impact depends on the application using python-dotenv and the privileges under which it runs.

Proof of Concept

The following script demonstrates the vulnerability. It requires /tmp and the user's home directory to reside on different devices (common on systemd-based Linux systems with tmpfs).

import os
import sys
import tempfile
from dotenv import set_key

# Pre-condition: /tmp must be on a different device than the target directory.
tmp_dev = os.stat("/tmp").st_dev
home_dev = os.stat(os.path.expanduser("~")).st_dev
assert tmp_dev != home_dev, "Skipped: /tmp and ~ are on the same device (no cross-device move)"

with tempfile.TemporaryDirectory(dir=os.path.expanduser("~")) as workdir:
    # File an attacker wants to overwrite
    target = os.path.join(workdir, "victim_config.txt")
    with open(target, "w") as f:
        f.write("DB_PASSWORD=supersecret\n")

    # Attacker pre-places a symlink at the path the application will use as .env
    env_symlink = os.path.join(workdir, ".env")
    os.symlink(target, env_symlink)

    before = open(target).read()

    # Application writes a new key -- triggers the cross-device fallback
    set_key(env_symlink, "INJECTED", "attacker_value")

    after = open(target).read()

    print("Before:", repr(before))
    print("After: ", repr(after))
    print("Symlink target overwritten:", target)

Expected output:

Before: 'DB_PASSWORD=supersecret\n'
After:  "DB_PASSWORD=supersecret\nINJECTED='attacker_value'\n"
Symlink target overwritten: /home/user/tmp806nut2g/victim_config.txt

Remediation

The fix changes the rewrite() context manager in the following ways:…

Record
GHSA-mf9w-mj56-hr94
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Weakness
CWE-59, CWE-61
Updated
2026-11-02
OSVOESA-2026-2198 6.6

python-dotenv security update

Python-dotenv reads key-value pairs from a .env file and can set them as environment variables. It helps in the development of applications following the 12-factor principles.

Security Fix(es):

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.(CVE-2026-28684)

Record
OESA-2026-2198
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
OSVOESA-2026-2199 6.6

python-dotenv security update

Python-dotenv reads key-value pairs from a .env file and can set them as environment variables. It helps in the development of applications following the 12-factor principles.

Security Fix(es):

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.(CVE-2026-28684)

Record
OESA-2026-2199
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
OSVOESA-2026-2324 6.6

python-dotenv security update

Python-dotenv reads key-value pairs from a .env file and can set them as environment variables. It helps in the development of applications following the 12-factor principles.

Security Fix(es):

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.(CVE-2026-28684)

Record
OESA-2026-2324
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
OSVPYSEC-2026-2270 6.6

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
PYSEC-2026-2270
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
OSVROOT-APP-PYPI-CVE-2026-28684 6.6

CVE-2026-28684 in python-dotenv - Patched by Root

Root has patched CVE-2026-28684 in the python-dotenv package for Root:PyPI. Multiple fixed versions available.

Record
ROOT-APP-PYPI-CVE-2026-28684
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
OSVUBUNTU-CVE-2026-28684 6.6

python-dotenv reads key-value pairs from a .env file and can set them as environment variables. Prior to version 1.2.2, 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. Users should upgrade to v.1.2.2 or, as a workaround, apply the patch manually.

Record
UBUNTU-CVE-2026-28684
CVSS 3.1
6.6 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H
Updated
2026-11-02
OSVopenSUSE-SU-2026:20952-1 No score

Security update for python-python-dotenv

This update for python-python-dotenv fixes the following issue:

  • CVE-2026-28684: Prior to version 1.2.2, 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 (bsc#1262423).
Record
openSUSE-SU-2026:20952-1
Updated
2026-11-02
OSVSUSE-SU-2026:22118-1 No score

Security update for python-python-dotenv

This update for python-python-dotenv fixes the following issue:

  • CVE-2026-28684: Prior to version 1.2.2, 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 (bsc#1262423).
Record
SUSE-SU-2026:22118-1
Updated
2026-11-02
OSVSUSE-SU-2026:2724-1 No score

Security update for python-python-dotenv

This update for python-python-dotenv fixes the following issue:

  • CVE-2026-28684: follow symbolic links when rewriting .env files (bsc#1262423)
Record
SUSE-SU-2026:2724-1
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
python-dotenv
PyPI
before 1.2.2
1.2.2
python-dotenv
Debian:12
All versions, plus listed versions
0.21.0-11.0.0-11.0.1-11.2.1-11.2.1-2
None known
python-dotenv
Debian:13
All versions, plus listed versions
1.0.1-11.2.1-11.2.1-2
None known
python-dotenv
Debian:14
All versions, plus listed versions
1.0.1-11.2.1-11.2.1-2
None known
python-dotenv
PyPI
before 1.2.2, plus listed versions
0.1.00.1.20.1.30.1.50.10.0
Show 44 moreShow less
0.10.10.10.20.10.30.10.40.10.50.11.00.12.00.13.00.14.00.15.00.16.00.17.00.17.10.18.00.19.00.19.10.19.20.2.00.20.00.21.00.21.10.3.00.4.00.5.00.5.10.6.00.6.10.6.20.6.30.6.40.6.50.7.00.7.10.8.00.8.10.8.20.9.00.9.11.0.01.0.11.1.01.1.11.2.01.2.1
1.2.2
python-dotenv
openEuler:24.03-LTS
before 1.2.2-1.oe2403
1.2.2-1.oe2403
python-dotenv
openEuler:24.03-LTS-SP1
before 1.2.2-1.oe2403sp1
1.2.2-1.oe2403sp1
python-dotenv
openEuler:24.03-LTS-SP3
before 1.2.2-1.oe2403sp3
1.2.2-1.oe2403sp3
python-dotenv
Root:PyPI
before 1.2.1+aikido.2
1.2.1+aikido.21.1.1+aikido.20.21.1+aikido.11.0.1+aikido.11.1.1+aikido.31.1.1+aikido.41.2.1+aikido.3
python-python-dotenv
SUSE:Linux Enterprise Server 16.0
before 1.1.0-160000.3.1
1.1.0-160000.3.1
Show 10 moreShow less
Affected packages
PackageAffectedFixed
python-python-dotenv
SUSE:Linux Enterprise Server for SAP applications 16.0
before 1.1.0-160000.3.1
1.1.0-160000.3.1
python-python-dotenv
SUSE:Linux Enterprise Module for Python 3 15 SP7
before 1.0.0-150400.9.6.1
1.0.0-150400.9.6.1
python-dotenv
Ubuntu:18.04:LTS
All versions, plus listed versions
0.7.1-1.1
None known
python-dotenv
Ubuntu:20.04:LTS
All versions, plus listed versions
0.9.1-1
None known
python-dotenv
Ubuntu:22.04:LTS
All versions, plus listed versions
0.15.0-10.19.0-10.19.2-1
None known
python-dotenv
Ubuntu:24.04:LTS
All versions, plus listed versions
1.0.0-11.0.1-1
None known
python-dotenv
Ubuntu:25.10
All versions, plus listed versions
1.0.1-1
None known
python-dotenv
Ubuntu:26.10
All versions, plus listed versions
1.0.1-1build11.2.1-2
None known
python-dotenv
Ubuntu:26.04:LTS
All versions, plus listed versions
1.0.1-11.0.1-1build1
None known
python-python-dotenv
openSUSE:Leap 16.0
before 1.1.0-160000.3.1
1.1.0-160000.3.1

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-28684 is a medium vulnerability (CVSS 6.6) in Saurabh-kumar Python-dotenv, published April 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.25%, the 16th percentile. Fixed in python-dotenv 1.2.2.

References

Show 12 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open