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

CVE-2026-34451

CVE-2026-34451

Description

Claude SDK for TypeScript provides access to the Claude API from server-side TypeScript or JavaScript applications. From version 0.79.0 to before version 0.81.0, the local filesystem memory tool in the Anthropic TypeScript SDK validated model-supplied paths using a string prefix check that did not append a trailing path separator. A model steered by prompt injection could supply a crafted path that resolved to a sibling directory sharing the memory root's name as a prefix, allowing reads and writes outside the sandboxed memory directory. This issue has been patched in version 0.81.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@anthropic-ai/sdknpm
>= 0.79.0, < 0.81.00.81.0

Affected products

1

Patches

1
0ac69b3438ee

fix(memory): append path separator in validatePath prefix check

2 files changed · +38 2
  • src/tools/memory/node.ts+2 2 modified
    @@ -73,7 +73,7 @@ async function validateNoSymlinkEscape(targetPath: string, memoryRoot: string):
       while (true) {
         try {
           const resolved = await fs.realpath(current);
    -      if (!resolved.startsWith(resolvedRoot)) {
    +      if (resolved !== resolvedRoot && !resolved.startsWith(resolvedRoot + path.sep)) {
             throw new Error(`Path would escape /memories directory via symlink`);
           }
           return;
    @@ -141,7 +141,7 @@ export class BetaLocalFilesystemMemoryTool implements MemoryToolHandlers {
     
         const resolvedPath = path.resolve(fullPath);
         const resolvedRoot = path.resolve(this.memoryRoot);
    -    if (!resolvedPath.startsWith(resolvedRoot)) {
    +    if (resolvedPath !== resolvedRoot && !resolvedPath.startsWith(resolvedRoot + path.sep)) {
           throw new Error(`Path ${memoryPath} would escape /memories directory`);
         }
     
    
  • tests/lib/tools/BetaLocalFilesystemMemoryTool.test.ts+36 0 modified
    @@ -510,6 +510,42 @@ describe('BetaLocalFilesystemMemoryTool', () => {
         });
       });
     
    +  describe('sibling directory prefix attack', () => {
    +    it('should reject symlink to a sibling directory whose name shares the memory root prefix', async () => {
    +      // Attack: create a sibling directory memories_backup next to memories,
    +      // then symlink from inside memories to it. Without the trailing separator
    +      // fix, validateNoSymlinkEscape's startsWith check would pass because
    +      // "/tmp/.../memories_backup".startsWith("/tmp/.../memories") is true.
    +      const memoriesDir = path.join(tempDir, 'memories');
    +      const siblingDir = path.join(tempDir, 'memories_backup');
    +      await fs.mkdir(siblingDir, { recursive: true });
    +      await fs.writeFile(path.join(siblingDir, 'secret.txt'), 'stolen data', 'utf-8');
    +
    +      // Symlink from inside memories to the sibling
    +      await fs.symlink(siblingDir, path.join(memoriesDir, 'escape_link'), 'dir');
    +
    +      await expect(
    +        tool.view({
    +          command: 'view',
    +          path: '/memories/escape_link/secret.txt',
    +        }),
    +      ).rejects.toThrow('would escape /memories directory');
    +    });
    +
    +    it('should reject path traversal to a sibling prefix-matching directory', async () => {
    +      const siblingDir = path.join(tempDir, 'memories_backup');
    +      await fs.mkdir(siblingDir, { recursive: true });
    +      await fs.writeFile(path.join(siblingDir, 'secret.txt'), 'stolen data', 'utf-8');
    +
    +      await expect(
    +        tool.view({
    +          command: 'view',
    +          path: '/memories/../memories_backup/secret.txt',
    +        }),
    +      ).rejects.toThrow('would escape /memories directory');
    +    });
    +  });
    +
       describe('symlink validation', () => {
         let outsideDir: string;
     
    

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.