Skip to main content
Glama
pathValidator.test.ts4.72 kB
/** * Tests for pathValidator security */ import { describe, it, expect, beforeEach } from 'vitest'; import { PathValidator } from '../../src/security/pathValidator.js'; import path from 'path'; describe('PathValidator Security Tests', () => { const mockWorkspace = '/Users/guybary/Documents/octocode-local-files/packages/octocode-local-files'; let validator: PathValidator; beforeEach(() => { validator = new PathValidator(mockWorkspace); }); describe('absolute path validation', () => { it('should ALLOW paths within workspace', () => { const result = validator.validate(`${mockWorkspace}/src`); expect(result.isValid).toBe(true); }); it('should ALLOW workspace root itself', () => { const result = validator.validate(mockWorkspace); expect(result.isValid).toBe(true); }); it('should BLOCK parent directory', () => { const parent = path.dirname(mockWorkspace); const result = validator.validate(parent); expect(result.isValid).toBe(false); expect(result.error).toContain('outside allowed directories'); }); it('should BLOCK grandparent directory', () => { const grandparent = path.dirname(path.dirname(mockWorkspace)); const result = validator.validate(grandparent); expect(result.isValid).toBe(false); }); it('should BLOCK sibling directory with similar name', () => { // This tests the startsWith bug: "octocode-local-files-other" starts with "octocode-local-files" const sibling = '/Users/guybary/Documents/octocode-local-files-other'; const result = validator.validate(sibling); expect(result.isValid).toBe(false); expect(result.error).toContain('outside allowed directories'); }); it('should BLOCK paths with similar prefix', () => { // Edge case: path that starts with workspace name but isn't under it const similar = '/Users/guybary/Documents/octocode-local-files2'; const result = validator.validate(similar); expect(result.isValid).toBe(false); }); }); describe('monorepo scenario', () => { it('should BLOCK access to parent package when workspace is a subpackage', () => { // Workspace: /packages/octocode-local-files // Should block: /packages/other-package // Should block: /node_modules const monorepoRoot = '/Users/guybary/Documents/octocode-local-files'; const result = validator.validate(monorepoRoot); expect(result.isValid).toBe(false); expect(result.error).toContain('outside allowed directories'); }); it('should BLOCK node_modules in parent directory', () => { const parentNodeModules = '/Users/guybary/Documents/octocode-local-files/node_modules'; const result = validator.validate(parentNodeModules); expect(result.isValid).toBe(false); }); }); describe('system paths', () => { it('should BLOCK /etc', () => { const result = validator.validate('/etc'); expect(result.isValid).toBe(false); }); it('should BLOCK /usr', () => { const result = validator.validate('/usr'); expect(result.isValid).toBe(false); }); it('should BLOCK /tmp', () => { const result = validator.validate('/tmp'); expect(result.isValid).toBe(false); }); it('should BLOCK home directory', () => { const result = validator.validate('/Users/guybary'); expect(result.isValid).toBe(false); }); }); describe('relative paths', () => { // When relative paths are resolved, they should be checked against workspace it('should handle relative paths correctly', () => { // Relative path that would resolve within workspace const validator2 = new PathValidator(process.cwd()); const result = validator2.validate('./src'); // This should resolve to absolute and validate expect(result.isValid).toBe(true); }); it('should BLOCK parent traversal with relative paths', () => { const result = validator.validate('../../../etc'); // This should resolve to absolute and be blocked expect(result.isValid).toBe(false); }); }); describe('edge cases', () => { it('should reject empty path', () => { const result = validator.validate(''); expect(result.isValid).toBe(false); expect(result.error).toContain('empty'); }); it('should handle paths with trailing slash', () => { const result = validator.validate(`${mockWorkspace}/src/`); expect(result.isValid).toBe(true); }); it('should handle paths with ./ components', () => { const result = validator.validate(`${mockWorkspace}/./src`); expect(result.isValid).toBe(true); }); }); });

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