VYPR
Medium severity5.3NVD Advisory· Published Mar 31, 2026· Updated Apr 20, 2026

CVE-2026-34452

CVE-2026-34452

Description

The Claude SDK for Python provides access to the Claude API from Python applications. From version 0.86.0 to before version 0.87.0, the async local filesystem memory tool in the Anthropic Python SDK validated that model-supplied paths resolved inside the sandboxed memory directory, but then returned the unresolved path for subsequent file operations. A local attacker able to write to the memory directory could retarget a symlink between validation and use, causing reads or writes to escape the sandbox. The synchronous memory tool implementation was not affected. This issue has been patched in version 0.87.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
anthropicPyPI
>= 0.86.0, < 0.87.00.87.0

Affected products

1

Patches

1
6599043eee6e

fix(memory): return resolved path from async _validate_path

2 files changed · +34 1
  • src/anthropic/lib/tools/_beta_builtin_memory_tool.py+1 1 modified
    @@ -653,7 +653,7 @@ async def _validate_path(self, path: str) -> AsyncPath:
     
             await _async_validate_no_symlink_escape(full_path, self.memory_root)
     
    -        return full_path
    +        return AsyncPath(resolved_path)
     
         @override
         async def view(self, command: BetaMemoryTool20250818ViewCommand) -> str:
    
  • tests/lib/tools/memory_tools/test_filesystem.py+33 0 modified
    @@ -945,6 +945,39 @@ async def test_path_validation_reject_paths_trying_to_escape_memories(
                     )
                 )
     
    +    async def test_validate_path_returns_resolved_path_not_symlink_target(
    +        self, async_local_filesystem_tool: BetaAsyncLocalFilesystemMemoryTool
    +    ) -> None:
    +        """_validate_path must return the resolved path so that subsequent file
    +        operations hit the real location, not the (potentially swappable) symlink.
    +
    +        Without this fix, an attacker could:
    +        1. Create /memories/link -> /memories/legit  (passes validation)
    +        2. Swap /memories/link -> /etc between validation and the file operation
    +        3. The file operation would follow the new symlink target
    +        """
    +        memories_path = Path(str(async_local_filesystem_tool.memory_root))
    +        memories_path.mkdir(parents=True, exist_ok=True)
    +
    +        # Create a real directory inside memories and a symlink pointing to it
    +        legit_dir = memories_path / "legit"
    +        legit_dir.mkdir()
    +        (legit_dir / "file.txt").write_text("content", encoding="utf-8")
    +
    +        link_path = memories_path / "link"
    +        os.symlink(legit_dir, link_path, target_is_directory=True)
    +
    +        # _validate_path should return the resolved real path, not the symlink path
    +        result = await async_local_filesystem_tool._validate_path("/memories/link/file.txt")
    +        result_str = str(result)
    +
    +        # The returned path should point to the resolved location (under legit/),
    +        # not through the symlink
    +        assert "link" not in result_str, (
    +            f"_validate_path returned unresolved symlink path: {result_str}"
    +        )
    +        assert str(legit_dir.resolve()) in result_str
    +
         async def test_symlink_validation_reject_symlink_pointing_outside_memories(
             self, async_local_filesystem_tool: BetaAsyncLocalFilesystemMemoryTool
         ) -> None:
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.