Skip to main content
Glama
symlink-attack.test.ts4.53 kB
/** * SYMLINK ATTACK TESTS - Most dangerous attack vector */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PathValidator } from '../../src/security/pathValidator.js'; import fs from 'fs'; import path from 'path'; describe('🔴 SYMLINK ATTACKS', () => { const workspace = '/Users/guybary/path_validator_symlink_test'; let validator: PathValidator; beforeAll(() => { // Create test workspace fs.mkdirSync(workspace, { recursive: true }); validator = new PathValidator(workspace); }); afterAll(() => { // Cleanup try { // Remove symlinks first const links = ['evil_link_etc', 'evil_link_root', 'evil_link_parent']; links.forEach(link => { try { fs.unlinkSync(path.join(workspace, link)); } catch { // Ignore cleanup errors } }); fs.rmdirSync(workspace); } catch { // Ignore cleanup errors } }); it('ATTACK: Symlink pointing to /etc', () => { const linkPath = path.join(workspace, 'evil_link_etc'); try { // Create symlink to /etc fs.symlinkSync('/etc', linkPath); console.log('\n🔴 ATTACK: Symlink to /etc'); console.log(` Symlink created: ${linkPath} -> /etc`); // Try to validate the symlink const result = validator.validate(linkPath); console.log(` Validation result: ${result.isValid ? '❌ BYPASSED!' : '✅ BLOCKED'}`); console.log(` Error: ${result.error || 'none'}`); console.log(` Sanitized: ${result.sanitizedPath || 'none'}`); // Should be blocked! expect(result.isValid).toBe(false); expect(result.error).toContain('outside allowed directories'); // Cleanup fs.unlinkSync(linkPath); } catch { // If we can't create symlink (permissions), test passes expect(true).toBe(true); } }); it('ATTACK: Symlink pointing to root directory', () => { const linkPath = path.join(workspace, 'evil_link_root'); try { fs.symlinkSync('/', linkPath); console.log('\n🔴 ATTACK: Symlink to /'); const result = validator.validate(linkPath); console.log(` Result: ${result.isValid ? '❌ BYPASSED!' : '✅ BLOCKED'}`); expect(result.isValid).toBe(false); fs.unlinkSync(linkPath); } catch { expect(true).toBe(true); } }); it('ATTACK: Symlink pointing to parent directory', () => { const linkPath = path.join(workspace, 'evil_link_parent'); const parentDir = path.dirname(workspace); try { fs.symlinkSync(parentDir, linkPath); console.log('\n🔴 ATTACK: Symlink to parent directory'); console.log(` Symlink: ${linkPath} -> ${parentDir}`); const result = validator.validate(linkPath); console.log(` Result: ${result.isValid ? '❌ BYPASSED!' : '✅ BLOCKED'}`); expect(result.isValid).toBe(false); expect(result.error).toContain('outside allowed directories'); fs.unlinkSync(linkPath); } catch { expect(true).toBe(true); } }); it('ATTACK: Symlink chain (link -> link -> /etc)', () => { const link1 = path.join(workspace, 'link1'); const link2 = path.join(workspace, 'link2'); try { fs.symlinkSync(link2, link1); fs.symlinkSync('/etc', link2); console.log('\n🔴 ATTACK: Symlink chain'); const result = validator.validate(link1); console.log(` Result: ${result.isValid ? '❌ BYPASSED!' : '✅ BLOCKED'}`); expect(result.isValid).toBe(false); fs.unlinkSync(link1); fs.unlinkSync(link2); } catch { expect(true).toBe(true); } }); it('SAFE: Symlink pointing within workspace', () => { const safeDir = path.join(workspace, 'safe_target'); const linkPath = path.join(workspace, 'safe_link'); try { fs.mkdirSync(safeDir); fs.symlinkSync(safeDir, linkPath); console.log('\n✅ SAFE: Symlink within workspace'); const result = validator.validate(linkPath); console.log(` Result: ${result.isValid ? '✅ ALLOWED (correct)' : '❌ BLOCKED (wrong)'}`); // This should be allowed - symlink within workspace expect(result.isValid).toBe(true); fs.unlinkSync(linkPath); fs.rmdirSync(safeDir); } catch (e: unknown) { const error = e as Error; console.log(` Error: ${error.message}`); } }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bgauryy/local-explorer-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server