import { describe, expect, it } from 'vitest'; import { parseGpoBackupMetadataXml } from '../../server/gpo/gpo-metadata-parser'; import type { VerifiedZipFile } from '../../server/gpo/zip-inventory'; const guid = '11111111-1111-4111-8111-111111111111'; function parse(xml: string) { return parseGpoBackupMetadataXml({ bytes: Buffer.from(xml), entry: { relativePath: 'synthetic/Backup.xml', sha256: 'a'.repeat(64) } } as unknown as VerifiedZipFile); } describe('GPMC metadata field paths', () => { it('reads names only from bounded template fields when explicitly requested', () => { const file = { bytes: Buffer.from('MSFT Windows Server 2016 - Domain ControllerWrong'), entry: { relativePath: 'Synthetic/GPReport.xml', sha256: 'a'.repeat(64) } } as unknown as VerifiedZipFile; expect(parseGpoBackupMetadataXml(file).templateNames).toBeUndefined(); expect(parseGpoBackupMetadataXml(file, undefined, true).templateNames).toEqual(['MSFT Windows Server 2016 - Domain Controller']); const withIdentity = { ...file, bytes: Buffer.from(`Arbitrary display name{${guid}}`) }; expect(parseGpoBackupMetadataXml(withIdentity, undefined, true).gpoId).toBe(guid); expect(parseGpoBackupMetadataXml(file, undefined, true).gpoId).toBeUndefined(); }); it('reads the GPMC core identity without interpreting unrelated IDs as a GPO', () => { const result = parse(` 22222222-2222-4222-8222-222222222222unrelated.example {${guid}}synthetic.example `); expect(result).toMatchObject({ gpoId: guid, domainKey: 'dns:synthetic.example', status: 'partial' }); expect(result.backupId).toBeUndefined(); expect(result.backupCreatedAt).toBeUndefined(); }); it('reads a nested GPReport Identifier and preserves missing backup-specific evidence', () => { const result = parse(`{${guid}} synthetic.example`); expect(result.gpoId).toBe(guid); expect(result.domainKey).toBe('dns:synthetic.example'); expect(result.diagnosticCodes).not.toContain('gpo-metadata-field-shape-invalid'); expect(result.diagnosticCodes).toContain('gpo-metadata-backup-id-missing'); }); it('keeps depth limits and rejects external entities', () => { expect(() => parse(''.repeat(129) + ''.repeat(129))).toThrow(); expect(() => parse(']>&e;')).toThrow(); }); });