import { createElement } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { describe, expect, it, vi } from 'vitest'; import type { FindingRecord } from '../../src/domain/finding'; import type { CanonicalAssessmentModel } from '../../src/domain/canonical-model'; import { POLICY_EVALUATION_ENGINE, type PolicyEvaluationResult, type StoredPolicyEvaluation } from '../../src/domain/policy-evaluation'; import type { StoredMicrosoftSecurityBaselineAnalysis } from '../../src/domain/microsoft-security-baseline-analysis'; import { baselineRemediation, buildPolicyGuidance, formatBaselineVariants } from '../../src/profiles/group-policy/guidance'; import { policyWebSearch } from '../../src/profiles/group-policy/web-search'; import { FindingReader } from '../../src/features/finding-reader/FindingReader'; import { appendPolicyObservationsToDataset } from '../../src/features/project-import/policy-observations-to-dataset'; import { loadCanonicalProjectWorkspace } from '../../src/features/project-import/load-canonical-project-workspace'; function result(): PolicyEvaluationResult { return { id: 'result', baselineId: 'baseline', baselineAnalysisId: 'analysis', baselineLabel: 'Synthetic security baseline', baselineState: 'explicit-recommendation', customerState: 'missing', classification: 'confirmed_configured_deviation', comparator: { comparator: { kind: 'equality' }, relation: 'different', baseline: { kind: 'integer', value: '1' } }, identity: { id: 'identity', scope: 'computer', target: { kind: 'registry-value', hive: 'HKEY_LOCAL_MACHINE', key: 'Software\\Policies\\Synthetic', valueName: 'Mode' }, admx: { status: 'matched', catalogId: 'catalog', reference: { technicalId: 'namespace#Mode' } } }, observationIds: [], backupInstanceIds: ['backup'], diagnosticCodes: [] } as unknown as PolicyEvaluationResult; } function evaluation(item = result()): StoredPolicyEvaluation { return { results: [item], run: { id: 'run', completedAt: '2026-09-06T00:00:00Z', evaluator: POLICY_EVALUATION_ENGINE, baselineAnalysisIds: ['analysis'] } } as StoredPolicyEvaluation; } function analysis(): StoredMicrosoftSecurityBaselineAnalysis { return { analysis: { id: 'analysis', baselineId: 'baseline', admxCatalog: { id: 'catalog', policies: [{ technicalId: 'namespace#Mode', sourcePath: 'Templates/Synthetic.admx', explainTextResourceId: 'Explain' }], languageResources: [ { admxFileName: 'Other.admx', locale: 'en-US', strings: { Explain: 'Wrong policy text' } }, { admxFileName: 'Synthetic.admx', locale: 'de-DE', strings: { Explain: 'Synthetischer Text' } }, { admxFileName: 'Synthetic.admx', locale: 'en-US', strings: { Explain: 'Original synthetic policy explanation.' } } ] } } } as unknown as StoredMicrosoftSecurityBaselineAnalysis; } function record(values: Record, title = 'Synthetic setting'): FindingRecord { return { id: 'synthetic', index: 0, title, filled: [], meta: [], fields: Object.entries(values).map(([label, value], index) => ({ index, label, value })) }; } function render(item: FindingRecord) { return renderToStaticMarkup(createElement(FindingReader, { record: item, title: item.title, linkedSheets: [], resultReferences: [], search: '', position: 0, recordCount: 1, toolId: 'group-policy', onPrevious() {}, onNext() {}, onReview() {} })); } describe('GPO baseline guidance', () => { it('distinguishes equal values from different templates and shows which template was selected', () => { const item = result(); item.identity.admx = { status: 'not-found' }; item.baselineSettingIds = ['dc']; item.baselineTemplateSelection = { status: 'selected', candidateSettingIds: ['dc', 'member'], contextIds: ['explicit'] }; const catalog = analysis(); catalog.analysis.settings = ['dc', 'member'].map(id => ({ id, baselineId: 'baseline', backupId: id, template: { names: [{ value: `Synthetic ${id}`, sourcePath: `Synthetic/${id}/Backup.xml`, sourceSha256: 'a'.repeat(64) }] }, identity: { status: 'resolved', identity: item.identity }, observation: { values: [{ kind: 'principal-set', principals: [] }] } })) as unknown as StoredMicrosoftSecurityBaselineAnalysis['analysis']['settings']; const text = buildPolicyGuidance([evaluation(item)], [catalog]).get(item.id)!.description; expect(text).toContain('Synthetic security baseline — Synthetic dc: Empty account list (selected)'); expect(text).toContain('Synthetic security baseline — Synthetic member: Empty account list'); expect(text.match(/Empty account list/g)).toHaveLength(2); expect(text).not.toContain('Source:'); expect(text).not.toContain('Backup:'); expect(text).not.toContain('could not be loaded'); }); it('shows distinct baseline values without source clutter or changing the outcome', () => { const item = result(); item.identity.admx = { status: 'not-found' }; item.diagnosticCodes = ['policy-evaluation-baseline-consensus-conflict']; item.baselineSettingIds = ['one', 'two', 'three']; const catalog = analysis(); catalog.analysis.settings = ['one', 'two', 'three', 'unrelated'].map((id, index) => ({ id, baselineId: 'baseline', backupId: `backup-${id}`, identity: { status: 'resolved', identity: item.identity }, observation: { sourcePath: `Synthetic/${id}/GptTmpl.inf`, values: [{ kind: 'principal-set', principals: index === 0 ? ['*S-1-5-32-544'] : [] }] } })) as StoredMicrosoftSecurityBaselineAnalysis['analysis']['settings']; const before = JSON.stringify([item, catalog]); const guidance = buildPolicyGuidance([evaluation(item)], [catalog]); const description = guidance.get(item.id)!.description; expect(description).toContain('Synthetic security baseline: Values: *S-1-5-32-544'); expect(description).toContain('Synthetic security baseline: Empty account list'); expect(description).not.toContain('Source:'); expect(description).not.toContain('Backup:'); expect(description.match(/Empty account list/g)).toHaveLength(1); expect(description).not.toContain('could not be loaded'); expect(description).not.toContain('unrelated'); const dataset = appendPolicyObservationsToDataset(null, 'Synthetic', [], [evaluation(item)], guidance)!; const [headers, row] = dataset.sheets[0].rows; expect(row[headers.indexOf('Description')]).toBe(description); expect(row[headers.indexOf('Status')]).toBe('Conflicts'); expect(render(record({ Description: description }))).toContain('Empty account list'); expect(JSON.stringify([item, catalog])).toBe(before); item.baselineSettingIds.push('missing'); expect(buildPolicyGuidance([evaluation(item)], [catalog]).get(item.id)!.description) .toContain('Some referenced baseline recommendations could not be loaded.'); catalog.analysis.id = 'different-revision'; const unavailable = buildPolicyGuidance([evaluation(item)], [catalog]).get(item.id)!.description; expect(unavailable).toContain('could not be loaded'); expect(unavailable).not.toContain('S-1-5-32-544'); }); it('highlights remediation without coloring description or sources', () => { const html = render(record({ Description: 'Synthetic explanation', Remediation: 'Expected: 1', Sources: 'Synthetic source' })); expect(html).toContain('

Remediation

'); expect(html.match(/class="reader-remediation"/g)).toHaveLength(1); expect(html).toContain('Expected: 1'); }); it('resolves English original text from the exact catalog and matching ADMX file', () => { const guidance = buildPolicyGuidance([evaluation()], [analysis()]).get('result')!; expect(guidance.description).toBe('Original synthetic policy explanation.'); expect(guidance.source).toBe('Imported baseline ADML · en-US · Synthetic.admx'); expect(guidance.remediation).toContain('HKEY_LOCAL_MACHINE\\Software\\Policies\\Synthetic\\Mode'); expect(guidance.remediation).toContain('Expected: 1'); }); it('never borrows descriptions from another version, baseline or ambiguous catalog', () => { for (const patch of [{ id: 'newer' }, { baselineId: 'different' }]) { const candidate = analysis(); Object.assign(candidate.analysis, patch); expect(buildPolicyGuidance([evaluation()], [candidate]).get('result')?.description).toBe(''); } const item = result(); item.identity.admx = { status: 'not-found' }; expect(buildPolicyGuidance([evaluation(item)], [analysis()]).get('result')?.description).toBe(''); const duplicate = analysis(); duplicate.analysis.admxCatalog.languageResources.push({ ...duplicate.analysis.admxCatalog.languageResources[2], strings: { Explain: 'Conflicting synthetic text' } }); expect(buildPolicyGuidance([evaluation()], [duplicate]).get('result')?.description).toBe(''); }); it('preserves zero and explicit audit flags, and does not invent absent recommendations', () => { const item = result(); item.comparator.baseline = { kind: 'integer', value: '0' }; expect(baselineRemediation(item)).toContain('Expected: 0'); item.comparator.baseline = { kind: 'audit-flags', success: true, failure: false }; expect(baselineRemediation(item)).toContain('Success: true'); expect(baselineRemediation(item)).toContain('Failure: false'); item.comparator.baseline = undefined; expect(baselineRemediation(item)).toBe(''); item.comparator.baseline = { kind: 'none' }; expect(baselineRemediation(item)).toBe(''); item.comparator.baseline = { kind: 'integer', value: '1' }; item.diagnosticCodes = ['policy-evaluation-baseline-consensus-conflict']; expect(baselineRemediation(item)).toBe(''); }); it('shows a missing customer state as Not configured and registry states in plain language', () => { const item = result(); item.identity.admx = { status: 'not-found' }; item.identity.target = { kind: 'registry-key', hive: 'HKEY_LOCAL_MACHINE', key: 'Software\\Policies\\Synthetic\\Blocklist' } as never; item.classification = 'configured_match'; const keyEmpty = { kind: 'registry-state', state: 'key-empty' } as const; const synthesizedAbsent = { kind: 'registry-state', state: 'absent' } as const; item.comparator = { version: 1, comparator: { kind: 'equality' }, relation: 'match', diagnosticCodes: [], actual: synthesizedAbsent, baseline: keyEmpty } as PolicyEvaluationResult['comparator']; item.baselineVariantAssessment = { version: 1, scope: 'backup-configuration', decision: 'all-pass', diagnosticCodes: [], actualValues: [], variants: [{ settingId: 'setting', comparator: item.comparator, baselineValues: [{ kind: 'registry-policy', key: 'Software\\Policies\\Synthetic\\Blocklist', operation: 'delete-all-values' }] }] } as unknown as PolicyEvaluationResult['baselineVariantAssessment']; const before = JSON.stringify(item); const guidance = buildPolicyGuidance([evaluation(item)], []); const [headers, row] = appendPolicyObservationsToDataset(null, 'Synthetic', [], [evaluation(item)], guidance)!.sheets[0].rows; const fields = Object.fromEntries(headers.map((header, index) => [String(header), String(row[index])])); expect(fields.Status).toBe('Pass'); expect(fields['Configured Value']).toBe('Not configured'); expect(fields.Description).toContain('Matches every assessed baseline variant'); expect(fields.Description).not.toContain('Registry type'); expect(fields.Description).not.toContain('State:'); const html = render(record(fields)); expect(html).toMatch(/Configured customer value<\/h4>]*>Not configured]*>No values under this key { const item = result(); item.comparator.comparator = { kind: 'minimum' }; expect(baselineRemediation(item)).toContain('Minimum: 1'); item.comparator.comparator = { kind: 'maximum' }; expect(baselineRemediation(item)).toContain('Maximum: 1'); }); it('projects guidance without modifying source records or outcomes', () => { const data = evaluation(); const before = JSON.stringify(data); const guidance = buildPolicyGuidance([data], [analysis()]); const dataset = appendPolicyObservationsToDataset(null, 'Synthetic', [], [data], guidance)!; const [headers, row] = dataset.sheets[0].rows; expect(row[headers.indexOf('Description')]).toBe('Original synthetic policy explanation.'); expect(row[headers.indexOf('Remediation')]).toContain('Expected: 1'); expect(row[headers.indexOf('Status')]).toBe('Not configured'); expect(JSON.stringify(data)).toBe(before); const missing = appendPolicyObservationsToDataset(null, 'Synthetic', [], [data])!; expect(missing.sheets[0].rows[1][headers.indexOf('Description')]).toBe('Description unavailable in the referenced baseline metadata.'); }); it('separates historical outcomes, current readiness and absent descriptions without modifying evidence', () => { const data = evaluation(); data.run.evaluator = { id: POLICY_EVALUATION_ENGINE.id, version: '1.3.3' }; const before = JSON.stringify(data); const [headers, row] = appendPolicyObservationsToDataset(null, 'Synthetic', [], [data])!.sheets[0].rows; const fields = Object.fromEntries(headers.map((header, index) => [String(header), String(row[index])])); expect(fields.Status).toBe('Review required'); expect(fields.Comparison).toBe('Historical comparison — re-evaluation required'); expect(fields['Historical result']).toBe('Not configured · Engine 1.3.3'); expect(fields['Evaluation readiness']).toContain(POLICY_EVALUATION_ENGINE.version); expect(fields.Description).not.toContain('Re-evaluation'); const html = render(record(fields)); expect(html).toContain('data-outcome="historical"'); expect(html).toContain('Saved baseline value'); expect(html).toContain('role="status"'); expect(JSON.stringify(data)).toBe(before); const failedGuidance = buildPolicyGuidance([data]); failedGuidance.get('result')!.descriptionLoadFailed = true; const failed = appendPolicyObservationsToDataset(null, 'Synthetic', [], [data], failedGuidance)!.sheets[0].rows; expect(failed[1][headers.indexOf('Description')]).toContain('could not be loaded'); }); it.each([false, true])('loads documentation once per referenced baseline; graceful failure=%s', async fails => { const stamp = '2026-09-06T00:00:00Z'; const model = { schemaVersion: 1, project: { id: 'project', name: 'Synthetic' }, assessment: { id: 'slot', projectId: 'project', name: 'Synthetic' }, scanRuns: [], importFiles: [], sourceTables: [], findingDefinitions: [], findingOccurrences: [], evidence: [], reviews: [], diagnostics: [] } as unknown as CanonicalAssessmentModel; const item = result(); item.observationIds = ['observation']; item.customerState = 'configured'; item.comparator.actual = { kind: 'integer', value: '0' }; const list = vi.fn(); if (fails) list.mockRejectedValue(new Error('synthetic unavailable')); else list.mockResolvedValue({ records: [analysis()] }); const reader = { listProjectAssessments: vi.fn().mockResolvedValue([model.assessment]), loadAssessmentModel: vi.fn().mockResolvedValue(model), listPolicyEvaluations: vi.fn().mockResolvedValue({ records: [evaluation(item)] }), listMicrosoftSecurityBaselineAnalyses: list, queryUnifiedResults: vi.fn().mockResolvedValue({ total: 1, limit: 500, offset: 0, items: [{ sourceKind: 'policy-observation', sourceResultId: 'observation', projectId: 'project', assessmentId: 'slot', title: 'Mode', importedAt: stamp, policyScope: 'computer', policyDeliveryMechanism: 'registry-policy', policyValues: [{ kind: 'registry-policy', key: 'Software\\Policies\\Synthetic', valueName: 'Mode', operation: 'set-value', typeCode: 4, data: { kind: 'uint32', value: 0 } }] }] }) }; const workspace = await loadCanonicalProjectWorkspace(reader, 'project'); expect(list).toHaveBeenCalledExactlyOnceWith('baseline'); const [headers, row] = workspace.dataset!.sheets[0].rows; expect(row[headers.indexOf('Description')]).toBe(fails ? 'Baseline description could not be loaded. The saved comparison is retained.' : 'Original synthetic policy explanation.'); expect(row[headers.indexOf('Remediation')]).toContain('Expected: 1'); }); }); describe('privacy-safe GPO web search', () => { it.each(['Domain', 'Private', 'Public'])('asks for the specific firewall setting and %s profile', profile => { const item = record({ 'Registry path': `HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\WindowsFirewall\\${profile}Profile`, Baseline: 'Windows Server 2022 Security Baseline - Synthetic Secret', 'Configured Value': 'private-value' }, 'AllowLocalPolicyMerge'); const search = policyWebSearch(item, 'group-policy')!; expect(search.query).toContain(`Windows Firewall AllowLocalPolicyMerge (${profile} profile)`); expect(search.query).toContain('Benchmark products: Windows Server 2022.'); expect(search.query).not.toContain('Synthetic Secret'); expect(search.query).not.toContain('HKEY_LOCAL_MACHINE'); expect(search.query).not.toContain('private-value'); expect(new URL(search.url).searchParams.get('q')).toBe(search.query); expect(new URL(search.url).searchParams.get('udm')).toBe('50'); }); it('does not guess a firewall setting from a partial match or unrelated registry path', () => { const item = record({ 'Registry path': 'SOFTWARE\\Policies\\Microsoft\\WindowsFirewall\\DomainProfile' }, 'AllowLocalPolicyMerge private-name'); expect(policyWebSearch(item, 'group-policy')?.query).not.toContain('AllowLocalPolicyMerge'); expect(policyWebSearch(item, 'group-policy')?.query).not.toContain('Windows Windows'); expect(policyWebSearch(record({ 'Registry path': 'SOFTWARE\\Synthetic' }, 'EnableFirewall'), 'group-policy')?.query).not.toContain('EnableFirewall'); }); it('excludes customer identifiers, file names, values and injected queries', () => { const sensitive = 'Synthetic Person synthetic.customer.invalid \\private\\file user@example.invalid'; const item = record({ Baseline: sensitive, Description: sensitive, Remediation: sensitive, 'Configured Value': sensitive, 'Registry path': sensitive, 'Search URL': 'https://evil.invalid/?q=' + sensitive, 'Source: File': sensitive }, sensitive); const search = policyWebSearch(item, 'group-policy')!; expect(search.query).toContain('Explain the Group Policy setting: Microsoft Group Policy.'); expect(new URL(search.url).searchParams.get('udm')).toBe('50'); expect(decodeURIComponent(search.url)).not.toContain('synthetic'); expect(policyWebSearch(item, 'cis-cat')).toBeUndefined(); }); it('uses only literal public topics even when uploaded metadata contains appended private text', () => { const item = record({ Baseline: 'Office Security Baseline - Synthetic Secret', 'Policy type': 'advanced-audit-policy' }); expect(policyWebSearch(item, 'group-policy')?.query).toContain('Microsoft Office / advanced audit policy.'); expect(policyWebSearch(item, 'group-policy')?.query).not.toContain('Synthetic Secret'); expect(policyWebSearch(record({}, 'ADPasswordEncryptionEnabled'), 'group-policy')?.query).toContain('Windows LAPS ADPasswordEncryptionEnabled'); expect(policyWebSearch(record({}, 'ADPasswordEncryptionEnabled Synthetic Secret'), 'group-policy')?.query).not.toContain('ADPasswordEncryptionEnabled'); expect(policyWebSearch(record({}, '__proto__'), 'group-policy')?.query).toContain('Explain the Group Policy setting: Microsoft Group Policy.'); }); it('renders an explicit no-referrer search link and inert original documentation', () => { const html = render(record({ Description: ' https://private.invalid/secret', Remediation: '[click](https://private.invalid)' })); expect(html).toContain('>AI search'); expect(html).toContain('rel="noopener noreferrer"'); expect(html).toContain('referrerPolicy="no-referrer"'); expect(html).toContain('<script>'); expect(html).not.toContain('href="https://private.invalid'); expect(html).not.toContain('