GHSA-3w55-933p-8pv5: High severity pip/strands-agents vulnerability
Summary
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.
Vulnerability Details
Component: strands-py/src/strands/session/filesessionmanager.py
Root Cause: 1. Default storage directory is tempfile.gettempdir() + "/strands/sessions/" (line 58) — resolves to /tmp/strands/sessions/ on Linux/macOS 2. The writefile() method (lines 116-123) writes to a predictable .tmp path without symlink protection: python tmp = f"{path}.tmp" with open(tmp, "w", encoding="utf-8", newline="\n") as f: json.dump(data, f, indent=2, ensureascii=False) os.replace(tmp, path) 3. open() follows symlinks — a pre-placed symlink at the .tmp path causes writes to an arbitrary target file 4. No integrity verification (HMAC/signature) on session files — tampered data is loaded as-is
Attack Vectors
1. Arbitrary File Overwrite (Local Privilege Escalation) 1. Attacker pre-creates /tmp/strands/sessions/session<id>/ (or monitors for new directories via inotify) 2. Attacker creates a symlink: session.json.tmp → /home/victim/.bashrc (or any writable file) 3. Victim application writes session data → follows symlink → overwrites target file with JSON content 4. Attacker achieves code execution on next shell login (or targets .ssh/authorizedkeys, cron files, etc.)
2. Persistent Prompt Injection via Session Tampering 1. Attacker writes crafted message files into the session directory 2. Victim application restores the session → loads attacker-controlled conversation history 3. Injected messages instruct the agent to execute attacker commands on every future interaction 4. No integrity check prevents this — the SDK trusts all session files at face value
Impact
- Arbitrary file overwrite — local attacker can write attacker-controlled content to any file writable by the victim process - Local privilege escalation — via overwriting shell configs, SSH keys, cron jobs, or systemd user services - Persistent agent compromise — via session data injection, the agent follows attacker instructions indefinitely
Reproduction
python import os, json, tempfile, shutil
Setup: simulate the vulnerable write pattern sessiondir = "/tmp/strands/sessions/sessiontest/" os.makedirs(sessiondir, existok=True)
Attacker: create symlink at the .tmp write path targetfile = "/tmp/symlinkattackproof.txt" with open(targetfile, "w") as f: f.write("ORIGINAL - should not be overwritten\n")
symlinkpath = os.path.join(sessiondir, "session.json.tmp") if os.path.exists(symlinkpath): os.unlink(symlinkpath) os.symlink(targetfile, symlinkpath)
Victim: FileSessionManager.writefile() equivalent with open(symlinkpath, "w", encoding="utf-8", newline="\n") as f: json.dump({"sessionid": "test", "injected": True}, f, indent=2)
Verify: target file overwritten with open(targetfile) as f: print(f"Target file content: {f.read()}") # Output: {"sessionid": "test", "injected": true}
Cleanup os.unlink(symlinkpath) os.unlink(targetfile) shutil.rmtree(sessiondir)
Suggested Fix
1. Use a user-private default directory — ~/.strands/sessions/ or $XDGDATAHOME/strands/sessions/ instead of /tmp/ 2. Use os.open() with ONOFOLLOW | OCREAT | OWRONLY — refuses to follow symlinks 3. Use tempfile.mkstemp() for atomic writes instead of predictable .tmp suffix 4. Verify directory ownership matches the current user before writing 5. Add optional integrity verification (HMAC) on session files to detect tampering
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/strands-agentsto a version that resolves this vulnerability.Fixed in 1.48.0 - Configuration
Store session data in a user-private directory rather than the default /tmp/strands/sessions/ directory.
FileSessionManager default storage directory = ~/.strands/sessions/ or $XDG_DATA_HOME/strands/sessions/ - Configuration
Add optional HMAC integrity verification for session files to detect tampering before loading them.
FileSessionManager session-file integrity verification = HMAC enabled - Compensating control
In FileSessionManager._write_file(), use os.open() with O_NOFOLLOW | O_CREAT | O_WRONLY so writes refuse to follow symlinks.
- Compensating control
Use tempfile.mkstemp() for atomic session-file writes instead of a predictable .tmp suffix.
- Compensating control
Before writing session data, verify that the session directory is owned by the current user.
Event History
Frequently Asked Questions
Who is exposed to this issue?
Systems using the FileSessionManager with its default session storage location are exposed, particularly on Linux or macOS where the path resolves to /tmp/strands/sessions/. Exploitation requires a local attacker who can place files or symbolic links in that world-writable location.
What does an attacker need to exploit the arbitrary file overwrite path?
The attacker needs local access and the ability to pre-place a symbolic link at a predictable temporary session-file path ending in .tmp. When the application writes session data, the file open operation follows that link and can write to the attacker-selected target.
Can session tampering affect future application behavior?
Yes. Session files have no HMAC, signature, or other integrity verification, so tampered session data is loaded as-is. An attacker able to modify session data can inject malicious session content for persistent prompt injection.
What configuration change can reduce exposure if patching is not immediately possible?
Avoid using the default /tmp/strands/sessions/ location for session storage. Configure session data to use a directory that is not world-writable and is protected from untrusted local users.