import { describe, it, expect } from 'vitest' import { existsSync, readFileSync } from 'node:fs' import { join } from 'node:path' import { AVATAR_OPTIONS, getAvatarUrl } from '../avatars' /** * These avatars used to be fetched from api.dicebear.com on every render, so * every authenticated page view of an accounting product told a third party * who was looking at it, and a firewalled or self-hosted install showed no * faces at all. The point of these tests is that the registry cannot quietly * drift back to a remote URL, and that every entry actually has a file. */ const PUBLIC_DIR = join(process.cwd(), 'public') describe('AVATAR_OPTIONS', () => { it('serves every avatar from our own origin', () => { for (const option of AVATAR_OPTIONS) { expect(option.url.startsWith('/'), `${option.id} must be a local path`).toBe(true) expect(option.url).not.toMatch(/^https?:/) expect(option.url).not.toContain('dicebear.com') } }) it('has a real file behind every entry', () => { // A registry entry with no file renders a broken image, which looks like a // bug in the agent rather than a missing asset. for (const option of AVATAR_OPTIONS) { expect(existsSync(join(PUBLIC_DIR, option.url)), `missing file for ${option.id}`).toBe(true) } }) it('ships avatars that make no network requests of their own', () => { // Self-hosting the file is pointless if the file then phones home. This // asserts the PROPERTY (nothing points off-origin) rather than a list of // elements: an allowlist of and xlink:href would still let a // future asset through via , , or a // scheme-relative //host, which is how this sort of guard rots. for (const option of AVATAR_OPTIONS) { const svg = readFileSync(join(PUBLIC_DIR, option.url), 'utf8') // Namespace declarations and the licence metadata legitimately contain // URLs and are never fetched, so they are removed before the check // rather than special-cased inside it. const referencing = svg .replace(//gi, '') .replace(/xmlns(:[a-z0-9-]+)?\s*=\s*"[^"]*"/gi, '') .replace(/xsi:type\s*=\s*"[^"]*"/gi, '') expect(referencing, `${option.id} references an absolute URL`).not.toMatch(/https?:\/\//i) // Scheme-relative: "//host/x" inherits the page's scheme and still // leaves the origin. expect(referencing, `${option.id} references a scheme-relative URL`).not.toMatch( /(href|src)\s*=\s*"\/\//i, ) expect(referencing).not.toMatch(/url\(\s*['"]?\/\//i) expect(referencing, `${option.id} contains a script`).not.toMatch(/