GHSA-3w55-933p-8pv5
GHSA-3w55-933p-8pv5 · Strands Agents: Local Privilege Escalation via Symlink Attack in Default Session File Storage
Esta página presenta datos de fuentes públicas de vulnerabilidades. Consulta el aviso original antes de actualizar.
## 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:** 1. Default storage directory is `tempfile.gettempdir() + "/strands/sessions/"` (line 58) — resolves to `/tmp/strands/sessions/` on Linux/macOS 2. The `_write_file()` 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, ensure_ascii=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/authorized_keys`, 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 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 1. **Use a user-private default directory** — `~/.strands/sessions/` or `$XDG_DATA_HOME/strands/sessions/` instead of `/tmp/` 2. **Use `os.open()` with `O_NOFOLLOW | O_CREAT | O_WRONLY`** — 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
CVSS 7.1 · Alta · Corrección disponible
- Publicación
- Actualización
Pila tecnológica: python
Productos y versiones afectados
strands-agents PyPI
- Versiones
- 0.0.1
- 0.1.0
- 0.1.1
- 0.1.2
- 0.1.3
- 0.1.4
- 0.1.5
- 0.1.6
- 0.1.7
- 0.1.8
- 0.1.9
- 0.2.0
- 0.2.1
- 0.3.0
- 1.0.0
- 1.0.1
- 1.1.0
- 1.10.0
- 1.11.0
- 1.12.0
- 1.13.0
- 1.14.0
- 1.15.0
- 1.16.0
- 1.17.0
- 1.18.0
- 1.19.0
- 1.2.0
- 1.20.0
- 1.21.0
- 1.22.0
- 1.23.0
- 1.24.0
- 1.25.0
- 1.26.0
- 1.27.0
- 1.28.0
- 1.29.0
- 1.3.0
- 1.30.0
- 1.31.0
- 1.32.0
- 1.33.0
- 1.34.0
- 1.34.1
- 1.35.0
- 1.36.0
- 1.37.0
- 1.38.0
- 1.39.0
- 1.4.0
- 1.40.0
- 1.41.0
- 1.42.0
- 1.43.0
- 1.44.0
- 1.45.0
- 1.46.0
- 1.47.0
- 1.5.0
- 1.6.0
- 1.7.0
- 1.7.1
- 1.8.0
- 1.9.0
- 1.9.1
- Intervalos de versiones afectados
- ECOSYSTEM: < 1.48.0
Actualiza a 1.48.0
Fuentes originales
- https://github.com/strands-agents/harness-sdk/security/advisories/GHSA-3w55-933p-8pv5
- https://github.com/strands-agents/harness-sdk/pull/2937
- https://github.com/strands-agents/harness-sdk/commit/8658b9e0d57427b77b69343262184d76d8e63e8f
- https://github.com/strands-agents/harness-sdk
- https://github.com/strands-agents/harness-sdk/releases/tag/python/v1.48.0
- https://osv.dev/vulnerability/GHSA-3w55-933p-8pv5