diff --git a/src/checks/authentication/auth-alternative-access.ts b/src/checks/authentication/auth-alternative-access.ts index d5353b9..1a6df90 100644 --- a/src/checks/authentication/auth-alternative-access.ts +++ b/src/checks/authentication/auth-alternative-access.ts @@ -7,6 +7,7 @@ interface AuthGateDetails { softAuthGate?: number; authRedirect?: number; testedPages?: number; + fetchErrors?: number; pageResults?: Array<{ url: string; classification: string; @@ -59,6 +60,20 @@ async function check(ctx: CheckContext): Promise { (authDetails.authRedirect ?? 0); const accessibleCount = authDetails.accessible ?? 0; const testedCount = authDetails.testedPages ?? 0; + const fetchErrors = authDetails.fetchErrors ?? 0; + + // If auth-gate-detection failed solely because pages couldn't be fetched + // (DNS failure, network error, etc.) rather than from detected auth responses, + // we have no signal about authentication. Skip rather than imply an auth problem. + if (gatedCount === 0 && fetchErrors > 0) { + return { + id, + category, + status: 'skip', + message: + 'auth-gate-detection failed due to fetch errors, not detected auth responses; cannot assess alternative access', + }; + } const detectedPaths: DetectedPath[] = []; diff --git a/test/unit/checks/auth-alternative-access.test.ts b/test/unit/checks/auth-alternative-access.test.ts index 598bfb8..a842c8a 100644 --- a/test/unit/checks/auth-alternative-access.test.ts +++ b/test/unit/checks/auth-alternative-access.test.ts @@ -71,6 +71,31 @@ describe('auth-alternative-access', () => { expect(result.message).toContain('errored'); }); + it('skips when auth-gate-detection failed due to fetch errors only', async () => { + // Simulates the early-return path in auth-gate-detection where every page + // failed to fetch (e.g. DNS NXDOMAIN). Details include fetchErrors but no + // gated/accessible counts. We should not emit auth-no-alternative here. + const result = await check.run( + makeCtx( + authGateResult('fail', { + totalPages: 1, + testedPages: 1, + fetchErrors: 1, + pageResults: [ + { + url: 'https://example-domain-not-resolving.com', + classification: 'accessible', + status: null, + error: 'fetch failed', + }, + ], + }), + ), + ); + expect(result.status).toBe('skip'); + expect(result.message).toContain('fetch errors'); + }); + it('skips when auth-gate-detection was skipped', async () => { const result = await check.run( makeCtx({