- Move top-level engine and e2e prefixed test files under domain folders - Update fixture path helpers after moving render and pen tests - Add lint coverage to prevent new top-level prefixed test files - Refresh testing docs for the new fig and layout paths
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import { describe, test, expect } from 'bun:test'
|
|
import { resolve, sep } from 'node:path'
|
|
|
|
// Test the resolveSafePath logic directly (extracted for testability)
|
|
function resolveSafePath(filePath: string, root: string): string {
|
|
const resolved = resolve(filePath)
|
|
const normalizedSep = root.endsWith('/') || root.endsWith('\\') ? '' : sep
|
|
if (!resolved.startsWith(root + normalizedSep) && resolved !== root) {
|
|
throw new Error(`Path is outside the allowed root: ${root}`)
|
|
}
|
|
return resolved
|
|
}
|
|
|
|
describe('MCP path scoping', () => {
|
|
const root = resolve('/tmp/mcp-test-root')
|
|
|
|
test('allows path inside root', () => {
|
|
expect(resolveSafePath(`${root}/design.fig`, root)).toBe(`${root}/design.fig`)
|
|
})
|
|
|
|
test('allows nested path inside root', () => {
|
|
expect(resolveSafePath(`${root}/sub/dir/file.fig`, root)).toBe(`${root}/sub/dir/file.fig`)
|
|
})
|
|
|
|
test('allows root itself', () => {
|
|
expect(resolveSafePath(root, root)).toBe(root)
|
|
})
|
|
|
|
test('rejects path outside root', () => {
|
|
expect(() => resolveSafePath('/etc/passwd', root)).toThrow('outside the allowed root')
|
|
})
|
|
|
|
test('rejects path traversal', () => {
|
|
expect(() => resolveSafePath(`${root}/../../../etc/passwd`, root)).toThrow(
|
|
'outside the allowed root'
|
|
)
|
|
})
|
|
|
|
test('rejects sibling directory', () => {
|
|
expect(() => resolveSafePath(`${root}/../other-root/file.fig`, root)).toThrow(
|
|
'outside the allowed root'
|
|
)
|
|
})
|
|
|
|
test('rejects root prefix trick (root-evil)', () => {
|
|
expect(() => resolveSafePath(`${root}-evil/file.fig`, root)).toThrow('outside the allowed root')
|
|
})
|
|
})
|