Files
webmail/lib/admin/__tests__/directory-url.test.ts
T

37 lines
1.6 KiB
TypeScript

// @vitest-environment node
import { afterEach, describe, expect, it, vi } from 'vitest';
import { checkExtensionDirectoryUrl } from '../directory-url';
// The server fetches the extension directory's JSON on an admin session's
// behalf and hands it back, so a directory URL on an internal address would
// read internal services for that session.
afterEach(() => {
vi.unstubAllEnvs();
});
describe('checkExtensionDirectoryUrl', () => {
it('refuses private, loopback and local addresses', async () => {
for (const url of ['http://127.0.0.1:3000', 'http://10.0.0.5', 'https://192.168.1.10/', 'http://[::1]/', 'http://localhost:8080', 'http://admin.localhost']) {
expect(await checkExtensionDirectoryUrl(url), url).toMatch(/private address|this host/);
}
});
it('accepts a public address and an empty value', async () => {
expect(await checkExtensionDirectoryUrl('https://203.0.113.5/')).toBeNull();
expect(await checkExtensionDirectoryUrl('')).toBeNull();
expect(await checkExtensionDirectoryUrl(undefined)).toBeNull();
});
it('refuses other schemes and embedded credentials', async () => {
expect(await checkExtensionDirectoryUrl('ftp://203.0.113.5/')).toMatch(/http\(s\)/);
expect(await checkExtensionDirectoryUrl('https://user:pw@203.0.113.5/')).toMatch(/credentials/);
expect(await checkExtensionDirectoryUrl('not a url')).toMatch(/valid URL/);
});
it('lets the operator allow a directory on their own network', async () => {
vi.stubEnv('EXTENSION_DIRECTORY_ALLOW_PRIVATE', 'true');
expect(await checkExtensionDirectoryUrl('http://10.0.0.5:3000')).toBeNull();
});
});