50 lines
2 KiB
TypeScript
50 lines
2 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
|
|
import { FetchDictionaryLoader } from '../dictionaries/loaders/fetch-loader';
|
|
|
|
describe('FetchDictionaryLoader — URL injection protection', () => {
|
|
const loader = new FetchDictionaryLoader('https://cdn.example.com/dictionaries');
|
|
|
|
it('rejects ../ path traversal', async () => {
|
|
await expect(loader.loadText('../../admin/secret')).rejects.toThrow('Path traversal detected');
|
|
});
|
|
|
|
it('rejects paths with embedded ..', async () => {
|
|
await expect(loader.loadText('foo/../../../etc/passwd')).rejects.toThrow(
|
|
'Path traversal detected',
|
|
);
|
|
});
|
|
|
|
it('rejects absolute paths starting with /', async () => {
|
|
await expect(loader.loadText('/admin/secret')).rejects.toThrow('Absolute paths are not allowed');
|
|
});
|
|
|
|
it('exists() returns false for traversal attempts instead of throwing', async () => {
|
|
const result = await loader.exists('../../admin/secret');
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('exists() returns false for absolute paths', async () => {
|
|
const result = await loader.exists('/admin/secret');
|
|
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('resolves normal relative paths correctly', () => {
|
|
const loader2 = new FetchDictionaryLoader('https://cdn.example.com/dictionaries');
|
|
|
|
// loadText will fail on fetch (no server), but should NOT throw injection errors
|
|
// We test the URL resolution by expecting a fetch error, not a security error
|
|
expect(loader2.loadText('english/words.txt')).rejects.toThrow();
|
|
});
|
|
|
|
it('handles base URL with trailing slash consistently', () => {
|
|
const loaderWithSlash = new FetchDictionaryLoader('https://cdn.example.com/dict/');
|
|
const loaderNoSlash = new FetchDictionaryLoader('https://cdn.example.com/dict');
|
|
|
|
// Both should reject traversal identically
|
|
expect(loaderWithSlash.loadText('../../secret')).rejects.toThrow('Path traversal detected');
|
|
expect(loaderNoSlash.loadText('../../secret')).rejects.toThrow('Path traversal detected');
|
|
});
|
|
});
|