diff --git a/src/main/daemon/permissions/tcc-denial-capture.ts b/src/main/daemon/permissions/tcc-denial-capture.ts index 5172fb1b3b7..f389b9340b7 100644 --- a/src/main/daemon/permissions/tcc-denial-capture.ts +++ b/src/main/daemon/permissions/tcc-denial-capture.ts @@ -12,6 +12,7 @@ import { type HelperOrigin } from '../../../shared/daemon-tcc-denial-capture' import { LOCAL_BUILD_COMPATIBILITY_CONTRACT } from '../../../shared/local-build-compatibility-contract' +import type { DeveloperPermissionStatus } from '../../../shared/developer-permissions-types' import type { EventProps } from '../../../shared/telemetry-events' import { msSinceWakeSignal } from '../../power/wake-signal-clock' import { isTelemetryEnabled, track } from '../../telemetry/client' @@ -150,17 +151,23 @@ export function releaseTccDenialCapture(start: TccDenialCaptureStart): void { } async function readFullDiskAccess(): Promise { + let status: DeveloperPermissionStatus try { // Lazy: the status reader reaches the provider modules that import this capture. const { getTerminalHostsFullDiskAccessStatus } = await import('./daemon-full-disk-access-status') - const status = await getTerminalHostsFullDiskAccessStatus() - return status === 'granted' || status === 'denied' || status === 'unsupported' - ? status - : 'unknown' - } catch { + // The import is an await: consent may have gone, and the reader probes the host and disk. + requireTelemetryConsent() + status = await getTerminalHostsFullDiskAccessStatus() + } catch (error) { + if (error instanceof TelemetryOptedOutError) { + throw error + } return 'unknown' } + return status === 'granted' || status === 'denied' || status === 'unsupported' + ? status + : 'unknown' } function helperOriginOf(identity: DaemonEndpointIdentity): HelperOrigin { diff --git a/src/main/daemon/permissions/testing/tcc-denial-capture.test.ts b/src/main/daemon/permissions/testing/tcc-denial-capture.test.ts index a3e0f152322..4cca5c77c96 100644 --- a/src/main/daemon/permissions/testing/tcc-denial-capture.test.ts +++ b/src/main/daemon/permissions/testing/tcc-denial-capture.test.ts @@ -88,6 +88,21 @@ describe('tcc denial capture', () => { result: { identity: 'resolved', executablePath: null }, skipped: [mocks.logVerdict, mocks.signatures, mocks.fullDiskAccess] }, + { + // The access reader is lazily imported, so it starts after an await of its own. + stage: 'log reader, before the lazily imported access reader', + probe: mocks.logVerdict, + result: { + logAccess: 'ok', + tccdAsked: 'no', + authValue: 'none', + authReason: 'none', + service: 'none', + requirementFailure: 'no', + kernelDeny: 'no' + }, + skipped: [mocks.fullDiskAccess] + }, { stage: 'log, signature and access probes', probe: mocks.signatures,