GHSA-3w55-933p-8pv5
Strands Agents: Local Privilege Escalation via Symlink Attack in Default Session File Storage
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/file_session_manager.py
Root Cause:
- Default storage directory is
tempfile.gettempdir() + "/strands/sessions/"(line 58) — resolves to/tmp/strands/sessions/on Linux/macOS - The
_write_file()method (lines 116-123) writes to a predictable.tmppath 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.tmppath causes writes to an arbitrary target file- No integrity verification (HMAC/signature) on session files — tampered data is loaded as-is
Attack Vectors
1. Arbitrary File Overwrite (Local Privilege Escalation)
- Attacker pre-creates
/tmp/strands/sessions/session_<id>/(or monitors for new directories via inotify) - Attacker creates a symlink:
session.json.tmp→/home/victim/.bashrc(or any writable file) - Victim application writes session data → follows symlink → overwrites target file with JSON content
- Attacker achieves code execution on next shell login (or targets
.ssh/authorized_keys, cron files, etc.)
2. Persistent Prompt Injection via Session Tampering
- Attacker writes crafted message files into the session directory
- Victim application restores the session → loads attacker-controlled conversation history
- Injected messages instruct the agent to execute attacker commands on every future interaction
- 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
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)
Suggested Fix
- Use a user-private default directory —
~/.strands/sessions/or$XDG_DATA_HOME/strands/sessions/instead of/tmp/ - Use
os.open()withO_NOFOLLOW | O_CREAT | O_WRONLY— refuses to follow symlinks - Use
tempfile.mkstemp()for atomic writes instead of predictable.tmpsuffix - Verify directory ownership matches the current user before writing
- Add optional integrity verification (HMAC) on session files to detect tampering
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- High
- Availability
- High
What each source reports
GitHub Advisories Score used 7.1
Strands Agents: Local Privilege Escalation via Symlink Attack in Default Session File Storage
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/file_session_manager.py
Root Cause:
- Default storage directory is
tempfile.gettempdir() + "/strands/sessions/"(line 58) — resolves to/tmp/strands/sessions/on Linux/macOS - The
_write_file()method (lines 116-123) writes to a predictable.tmppath 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.tmppath causes writes to an arbitrary target file- No integrity verification (HMAC/signature) on session files — tampered data is loaded as-is
Attack Vectors
1. Arbitrary File Overwrite (Local Privilege Escalation)
- Attacker pre-creates
/tmp/strands/sessions/session_<id>/(or monitors for new directories via inotify) - Attacker creates a symlink:
session.json.tmp→/home/victim/.bashrc(or any writable file) - Victim application writes session data → follows symlink → overwrites target file with JSON content
- Attacker achieves code execution on next shell login (or targets
.ssh/authorized_keys, cron files, etc.)
2. Persistent Prompt Injection via Session Tampering
- Attacker writes crafted message files into the session directory
- Victim application restores the session → loads attacker-controlled conversation history
- Injected messages instruct the agent to execute attacker commands on every future interaction
- 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
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)
Suggested Fix
- Use a user-private default directory —
~/.strands/sessions/or$XDG_DATA_HOME/strands/sessions/instead of/tmp/ - Use
os.open()withO_NOFOLLOW | O_CREAT | O_WRONLY— refuses to follow symlinks - Use
tempfile.mkstemp()for atomic writes instead of predictable.tmpsuffix - Verify directory ownership matches the current user before writing
- Add optional integrity verification (HMAC) on session files to detect tampering
- Record
GHSA-3w55-933p-8pv5- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H - Weakness
- CWE-59
- Updated
- 2026-11-02
OSV 7.1
Strands Agents: Local Privilege Escalation via Symlink Attack in Default Session File Storage
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/file_session_manager.py
Root Cause:
- Default storage directory is
tempfile.gettempdir() + "/strands/sessions/"(line 58) — resolves to/tmp/strands/sessions/on Linux/macOS - The
_write_file()method (lines 116-123) writes to a predictable.tmppath 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.tmppath causes writes to an arbitrary target file- No integrity verification (HMAC/signature) on session files — tampered data is loaded as-is
Attack Vectors
1. Arbitrary File Overwrite (Local Privilege Escalation)
- Attacker pre-creates
/tmp/strands/sessions/session_<id>/(or monitors for new directories via inotify) - Attacker creates a symlink:
session.json.tmp→/home/victim/.bashrc(or any writable file) - Victim application writes session data → follows symlink → overwrites target file with JSON content
- Attacker achieves code execution on next shell login (or targets
.ssh/authorized_keys, cron files, etc.)
2. Persistent Prompt Injection via Session Tampering
- Attacker writes crafted message files into the session directory
- Victim application restores the session → loads attacker-controlled conversation history
- Injected messages instruct the agent to execute attacker commands on every future interaction
- 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
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)
Suggested Fix
- Use a user-private default directory —
~/.strands/sessions/or$XDG_DATA_HOME/strands/sessions/instead of/tmp/ - Use
os.open()withO_NOFOLLOW | O_CREAT | O_WRONLY— refuses to follow symlinks - Use
tempfile.mkstemp()for atomic writes instead of predictable.tmpsuffix - Verify directory ownership matches the current user before writing
- Add optional integrity verification (HMAC) on session files to detect tampering
- Record
GHSA-3w55-933p-8pv5- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H - Weakness
- CWE-59
- Updated
- 2026-11-02
Affected packages
| Package | Affected | Fixed |
|---|---|---|
strands-agentsPyPI | before 1.48.0 | 1.48.0 |
strands-agentsPyPI | before 1.48.0, plus listed versions 0.0.10.1.00.1.10.1.20.1.3 Show 45 moreShow less0.1.40.1.50.1.60.1.70.1.80.1.90.2.00.2.10.3.01.0.01.0.11.1.01.10.01.11.01.12.01.13.01.14.01.15.01.16.01.17.01.18.01.19.01.2.01.20.01.21.01.22.01.23.01.24.01.25.01.26.01.27.01.28.01.29.01.3.01.30.01.31.01.32.01.33.01.34.01.34.11.35.01.36.01.37.01.38.01.39.0 | 1.48.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | GitHub Advisories, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
GHSA-3w55-933p-8pv5 is a high vulnerability (CVSS 7.1) in strands-agents, published October 27, 2026. No source lists public exploit code. Fixed in strands-agents 1.48.0.
References
github.com/strands-agents/harness-sdk/security/advisories/GHSA-3w55-933p-8pv5
github.com/strands-agents/harness-sdk/pull/2937
github.com/strands-agents/harness-sdk/commit/8658b9e0d57427b77b69343262184d76d8e63e8f
github.com/strands-agents/harness-sdk/releases/tag/python/v1.48.0
github.com/advisories/GHSA-3w55-933p-8pv5
github.com/strands-agents/harness-sdk
Left out here: 16 versions. The JSON record has them.