= {
+ critical: "bg-red-100 text-red-700 border-red-200",
+ error: "bg-red-100 text-red-700 border-red-200",
+ warning: "bg-amber-100 text-amber-700 border-amber-200",
+ info: "bg-blue-100 text-blue-700 border-blue-200",
+ clean: "bg-emerald-100 text-emerald-700 border-emerald-200",
+};
+
+function pickDominant(events: EnrollmentEvent[]): { shutdown: EnrollmentEvent | null; startup: EnrollmentEvent | null; any: EnrollmentEvent | null } {
+ const analyses = events
+ .filter((e) => e.eventType === "integrity_bypass_analysis")
+ .sort((a, b) => a.sequence - b.sequence);
+ const shutdown = [...analyses].reverse().find((e) => (e.data as AnalysisPayload | undefined)?.triggered_at === "shutdown") ?? null;
+ const startup = analyses.find((e) => (e.data as AnalysisPayload | undefined)?.triggered_at === "startup") ?? null;
+ const any = shutdown ?? startup ?? (analyses.length > 0 ? analyses[analyses.length - 1] : null);
+ return { shutdown, startup, any };
+}
+
+function severityLabel(sev?: string, findings?: string[]): string {
+ if (!sev) return "unknown";
+ const lower = sev.toLowerCase();
+ if (lower === "info" && findings && findings.includes("no_bypass_indicators")) return "clean";
+ return lower;
+}
+
+function describeTpm(v: boolean | null | undefined): string {
+ if (v === true) return "TPM enabled";
+ if (v === false) return "TPM missing / disabled";
+ return "TPM status unknown";
+}
+
+function describeSecureBoot(v: boolean | null | undefined): string {
+ if (v === true) return "SecureBoot enabled";
+ if (v === false) return "SecureBoot disabled";
+ return "SecureBoot status unknown";
+}
+
+export default function IntegrityBypassSection({ events, expanded, setExpanded }: IntegrityBypassSectionProps) {
+ const { shutdown, startup, any } = useMemo(() => pickDominant(events), [events]);
+ const primary = shutdown ?? any;
+
+ if (!primary) return null;
+
+ const payload = (primary.data ?? {}) as AnalysisPayload;
+ const severity = severityLabel(payload.severity, payload.findings);
+ const badgeClass = severityBadgeColors[severity] ?? "bg-gray-100 text-gray-700 border-gray-200";
+
+ const activeBypasses = payload.checks?.lab_config?.active_bypasses ?? [];
+ const labValues = payload.checks?.lab_config?.values ?? {};
+ const moSetupFlagged = payload.checks?.mo_setup?.flagged === true;
+ const pchcFlagged = payload.checks?.pchc_upgrade_eligibility?.any_user_with_flag === true;
+ const pchcUsers = payload.checks?.pchc_upgrade_eligibility?.users_with_flag ?? [];
+ const setupScripts = (payload.checks?.setup_scripts ?? []).filter((s) => s.exists === true);
+ const corr = payload.checks?.correlation ?? {};
+
+ // Delta summary (startup vs shutdown) — focus on the facts that change in practice
+ const startupPayload = (startup?.data ?? {}) as AnalysisPayload | undefined;
+ const startupActive = startupPayload?.checks?.lab_config?.active_bypasses ?? [];
+ const newlyAppeared = activeBypasses.filter((b) => !startupActive.includes(b));
+ const newScripts = setupScripts.filter((s) => {
+ const startScripts = startupPayload?.checks?.setup_scripts ?? [];
+ return !startScripts.some((ss) => ss.path === s.path && ss.exists === true);
+ });
+
+ return (
+
+
setExpanded(!expanded)}
+ className="flex items-center justify-between w-full text-left cursor-pointer"
+ >
+
+
+
Integrity Bypass Analyzer
+
+ {severity.toUpperCase()}
+
+ {payload.finding && (
+
{payload.finding}
+ )}
+
+
+
+
+ {expanded && (
+
+ {/* Correlation row — always visible to give context */}
+
+
+ {describeTpm(corr.tpm_present_and_enabled)}
+
+
+ {describeSecureBoot(corr.secure_boot_enabled)}
+
+ {startup && shutdown && (
+
+ Startup + Shutdown checks available
+
+ )}
+
+
+ {/* LabConfig bypass keys */}
+
+
LabConfig — Install-time bypass keys
+ {!payload.checks?.lab_config?.key_exists ? (
+
HKLM\SYSTEM\Setup\LabConfig not present — normal on standard Windows installs.
+ ) : activeBypasses.length === 0 ? (
+
Key exists but no bypass values set to 1 (possible manipulated install medium, currently dormant).
+ ) : (
+
+ {Object.entries(labValues).map(([name, value]) => {
+ const active = value === 1;
+ const newlyActive = active && newlyAppeared.includes(name);
+ return (
+ -
+
+ {name} = {value}
+ {newlyActive && (
+ appeared during enrollment
+ )}
+
+ );
+ })}
+
+ )}
+
+
+ {/* MoSetup upgrade bypass */}
+
+
MoSetup — In-place upgrade bypass
+
+ AllowUpgradesWithUnsupportedTPMOrCPU{" "}
+ {moSetupFlagged ? (
+ = 1 (bypass active)
+ ) : (
+ not set / = 0
+ )}
+
+
+
+ {/* PCHC UpgradeEligibility */}
+
+
PCHC — Windows Update eligibility bypass
+ {pchcFlagged ? (
+
+
+ HKU\<SID>\SOFTWARE\Microsoft\PCHC\UpgradeEligibility = 1 found for {pchcUsers.length} user{pchcUsers.length === 1 ? '' : 's'}:
+
+
+ {pchcUsers.map((sid) => (
+ - {sid}
+ ))}
+
+
+ ) : (
+
No user hive has UpgradeEligibility = 1.
+ )}
+
+
+ {/* Setup scripts */}
+
+
Setup Scripts — %WINDIR%\Setup\Scripts\
+ {setupScripts.length === 0 ? (
+
No SetupComplete.cmd / ErrorHandler.cmd present.
+ ) : (
+
+ {setupScripts.map((s) => {
+ const isNew = newScripts.some((ns) => ns.path === s.path);
+ return (
+ -
+
+ {s.path}
+ ({s.size_bytes ?? 0} bytes{s.last_modified_utc ? `, modified ${new Date(s.last_modified_utc).toISOString().replace('T', ' ').substring(0, 19)} UTC` : ""})
+ {isNew && (
+ appeared during enrollment
+ )}
+
+ );
+ })}
+
+ )}
+
+
+ {/* Findings list */}
+ {payload.findings && payload.findings.length > 0 && payload.findings[0] !== "no_bypass_indicators" && (
+
+
Findings
+
+ {payload.findings.map((f) => (
+ - {f}
+ ))}
+
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/hooks/useSessionTenantConfig.ts b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/hooks/useSessionTenantConfig.ts
index e9719155..c228b94b 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/hooks/useSessionTenantConfig.ts
+++ b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/hooks/useSessionTenantConfig.ts
@@ -7,6 +7,7 @@ import { authenticatedFetch } from "@/lib/authenticatedFetch";
interface UseSessionTenantConfigReturn {
showScriptOutput: boolean;
enableSoftwareInventoryAnalyzer: boolean;
+ enableIntegrityBypassAnalyzer: boolean;
}
/**
@@ -20,6 +21,7 @@ export function useSessionTenantConfig(
): UseSessionTenantConfigReturn {
const [showScriptOutput, setShowScriptOutput] = useState(true);
const [enableSoftwareInventoryAnalyzer, setEnableSoftwareInventoryAnalyzer] = useState(false);
+ const [enableIntegrityBypassAnalyzer, setEnableIntegrityBypassAnalyzer] = useState(true);
useEffect(() => {
if (!sessionTenantId) return;
@@ -32,10 +34,11 @@ export function useSessionTenantConfig(
if (cancelled) return;
setShowScriptOutput(cfg.showScriptOutput ?? true);
setEnableSoftwareInventoryAnalyzer(cfg.enableSoftwareInventoryAnalyzer ?? false);
+ setEnableIntegrityBypassAnalyzer(cfg.enableIntegrityBypassAnalyzer ?? true);
} catch { /* non-fatal */ }
})();
return () => { cancelled = true; };
}, [sessionTenantId, getAccessToken]);
- return { showScriptOutput, enableSoftwareInventoryAnalyzer };
+ return { showScriptOutput, enableSoftwareInventoryAnalyzer, enableIntegrityBypassAnalyzer };
}
diff --git a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx
index 29e9e837..923a1602 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/page.tsx
@@ -28,6 +28,7 @@ import PhaseTimeline from "./components/PhaseTimeline";
import EventTimeline from "./components/EventTimeline";
import AnalysisResultsSection from "./components/AnalysisResultsSection";
import VulnerabilityReportSection from "./components/VulnerabilityReportSection";
+import IntegrityBypassSection from "./components/IntegrityBypassSection";
import AdminOverrideModal from "./components/AdminOverrideModal";
import ReportSessionModal from "./components/ReportSessionModal";
import { usePageSections } from "../../../hooks/usePageSections";
@@ -51,6 +52,7 @@ export default function SessionDetailPage() {
const [reportSubmitting, setReportSubmitting] = useState(false);
const [analysisExpanded, setAnalysisExpanded] = useState(true);
const [vulnerabilityReportExpanded, setVulnerabilityReportExpanded] = useState(false);
+ const [integrityBypassExpanded, setIntegrityBypassExpanded] = useState(false);
const [phaseTimelineExpanded, setPhaseTimelineExpanded] = useState(true);
const [perfExpanded, setPerfExpanded] = useState(true);
const [timelineExpanded, setTimelineExpanded] = useState(true);
@@ -103,7 +105,7 @@ export default function SessionDetailPage() {
const { session, setSession, sessionTenantId, loading } = detail;
const events = eventsApi.events;
const { analysisResults, loadingAnalysis, vulnerabilityReport, fetchAnalysisResults, fetchVulnerabilityReport } = analysis;
- const { showScriptOutput, enableSoftwareInventoryAnalyzer } = tenantConfig;
+ const { showScriptOutput, enableSoftwareInventoryAnalyzer, enableIntegrityBypassAnalyzer } = tenantConfig;
const {
filteredEvents,
appSummaryStats,
@@ -512,6 +514,17 @@ export default function SessionDetailPage() {
)}
+ {/* Integrity Bypass — only when analyzer is enabled for this tenant and the session has produced at least one event */}
+ {!isGatherRulesSession && enableIntegrityBypassAnalyzer && (
+
+
+
+ )}
+
{/* Performance Metrics (from performance_snapshot events) */}
{!isGatherRulesSession && (
diff --git a/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx b/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx
index 30f49053..cf630849 100644
--- a/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/TenantConfigContext.tsx
@@ -92,6 +92,8 @@ interface TenantConfigContextValue {
setNewAllowedAccount: (v: string) => void;
enableSoftwareInventoryAnalyzer: boolean;
setEnableSoftwareInventoryAnalyzer: (v: boolean) => void;
+ enableIntegrityBypassAnalyzer: boolean;
+ setEnableIntegrityBypassAnalyzer: (v: boolean) => void;
handleSaveAgentAnalyzers: () => void;
handleResetAgentAnalyzers: () => void;
@@ -307,6 +309,7 @@ export function TenantConfigProvider({ children }: { children: React.ReactNode }
const [localAdminAllowedAccounts, setLocalAdminAllowedAccounts] = useState([]);
const [newAllowedAccount, setNewAllowedAccount] = useState("");
const [enableSoftwareInventoryAnalyzer, setEnableSoftwareInventoryAnalyzer] = useState(false);
+ const [enableIntegrityBypassAnalyzer, setEnableIntegrityBypassAnalyzer] = useState(true);
// Unrestricted mode
const [unrestrictedMode, setUnrestrictedMode] = useState(false);
@@ -413,6 +416,7 @@ export function TenantConfigProvider({ children }: { children: React.ReactNode }
setLocalAdminAllowedAccounts([]);
}
setEnableSoftwareInventoryAnalyzer(data.enableSoftwareInventoryAnalyzer ?? false);
+ setEnableIntegrityBypassAnalyzer(data.enableIntegrityBypassAnalyzer ?? true);
setUnrestrictedMode(data.unrestrictedMode ?? false);
// Parse SAS expiry and fire notification to bell if needed
@@ -599,6 +603,7 @@ export function TenantConfigProvider({ children }: { children: React.ReactNode }
enableLocalAdminAnalyzer,
localAdminAllowedAccountsJson: localAdminAllowedAccounts.length > 0 ? JSON.stringify(localAdminAllowedAccounts) : "",
enableSoftwareInventoryAnalyzer,
+ enableIntegrityBypassAnalyzer,
unrestrictedMode,
};
@@ -646,7 +651,8 @@ export function TenantConfigProvider({ children }: { children: React.ReactNode }
slaNotifyOnSuccessRateBreach, slaSuccessRateNotifyThreshold, slaNotifyOnDurationBreach,
slaNotifyOnAppInstallBreach, slaNotifyOnConsecutiveFailures, slaConsecutiveFailureThreshold,
diagnosticsBlobSasUrl, diagnosticsUploadMode, tenantDiagPaths,
- enableLocalAdminAnalyzer, localAdminAllowedAccounts, enableSoftwareInventoryAnalyzer, unrestrictedMode,
+ enableLocalAdminAnalyzer, localAdminAllowedAccounts, enableSoftwareInventoryAnalyzer,
+ enableIntegrityBypassAnalyzer, unrestrictedMode,
]);
// -----------------------------------------------------------------------
@@ -837,6 +843,7 @@ export function TenantConfigProvider({ children }: { children: React.ReactNode }
} catch { setLocalAdminAllowedAccounts([]); }
setNewAllowedAccount("");
setEnableSoftwareInventoryAnalyzer(config.enableSoftwareInventoryAnalyzer ?? false);
+ setEnableIntegrityBypassAnalyzer(config.enableIntegrityBypassAnalyzer ?? true);
}, [config]);
const handleSaveNotifications = useCallback(() => saveConfiguration("notifications"), [saveConfiguration]);
@@ -1191,6 +1198,7 @@ export function TenantConfigProvider({ children }: { children: React.ReactNode }
localAdminAllowedAccounts, setLocalAdminAllowedAccounts,
newAllowedAccount, setNewAllowedAccount,
enableSoftwareInventoryAnalyzer, setEnableSoftwareInventoryAnalyzer,
+ enableIntegrityBypassAnalyzer, setEnableIntegrityBypassAnalyzer,
handleSaveAgentAnalyzers, handleResetAgentAnalyzers,
// Unrestricted mode
diff --git a/src/Web/autopilot-monitor-web/app/settings/agent/sections/SectionAgentAnalyzers.tsx b/src/Web/autopilot-monitor-web/app/settings/agent/sections/SectionAgentAnalyzers.tsx
index 3222b935..ba771738 100644
--- a/src/Web/autopilot-monitor-web/app/settings/agent/sections/SectionAgentAnalyzers.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/agent/sections/SectionAgentAnalyzers.tsx
@@ -10,6 +10,7 @@ export function SectionAgentAnalyzers() {
localAdminAllowedAccounts, setLocalAdminAllowedAccounts,
newAllowedAccount, setNewAllowedAccount,
enableSoftwareInventoryAnalyzer, setEnableSoftwareInventoryAnalyzer,
+ enableIntegrityBypassAnalyzer, setEnableIntegrityBypassAnalyzer,
handleSaveAgentAnalyzers, handleResetAgentAnalyzers,
savingSection,
} = useTenantConfig();
@@ -26,6 +27,8 @@ export function SectionAgentAnalyzers() {
setNewAllowedAccount={setNewAllowedAccount}
enableSoftwareInventoryAnalyzer={enableSoftwareInventoryAnalyzer}
setEnableSoftwareInventoryAnalyzer={setEnableSoftwareInventoryAnalyzer}
+ enableIntegrityBypassAnalyzer={enableIntegrityBypassAnalyzer}
+ setEnableIntegrityBypassAnalyzer={setEnableIntegrityBypassAnalyzer}
onSave={handleSaveAgentAnalyzers}
onReset={handleResetAgentAnalyzers}
saving={savingSection === "agentAnalyzers"}
diff --git a/src/Web/autopilot-monitor-web/app/settings/components/AgentAnalyzersSection.tsx b/src/Web/autopilot-monitor-web/app/settings/components/AgentAnalyzersSection.tsx
index 6fef97cc..3d1d892c 100644
--- a/src/Web/autopilot-monitor-web/app/settings/components/AgentAnalyzersSection.tsx
+++ b/src/Web/autopilot-monitor-web/app/settings/components/AgentAnalyzersSection.tsx
@@ -11,6 +11,8 @@ interface AgentAnalyzersSectionProps {
setNewAllowedAccount: (value: string) => void;
enableSoftwareInventoryAnalyzer: boolean;
setEnableSoftwareInventoryAnalyzer: (value: boolean) => void;
+ enableIntegrityBypassAnalyzer: boolean;
+ setEnableIntegrityBypassAnalyzer: (value: boolean) => void;
onSave: () => Promise | void;
onReset: () => void;
saving: boolean;
@@ -39,6 +41,8 @@ export default function AgentAnalyzersSection({
setNewAllowedAccount,
enableSoftwareInventoryAnalyzer,
setEnableSoftwareInventoryAnalyzer,
+ enableIntegrityBypassAnalyzer,
+ setEnableIntegrityBypassAnalyzer,
onSave,
onReset,
saving,
@@ -193,6 +197,34 @@ export default function AgentAnalyzersSection({
+ {/* ── Divider ─────────────────────────────────────── */}
+
+
+ {/* ── Integrity Bypass Analyzer ───────────────────── */}
+
+
Integrity Bypass Analyzer
+
+ Detects Windows 11 "unsupported hardware" installations where PC Health Check / Setup-time gates were bypassed
+ (LabConfig TPM / SecureBoot / CPU / RAM / Disk bypass keys, MoSetup upgrade flag, PCHC UpgradeEligibility).
+ Also flags suspicious post-OOBE SetupComplete.cmd / ErrorHandler.cmd scripts.
+ Results are correlated against current TPM and SecureBoot state.
+
+
+ {/* Enable toggle */}
+
+
+
Enable Integrity Bypass Analyzer
+
Run at enrollment start and completion to surface devices with bypassed Win11 hardware gates
+
+
+
+
+
{/* Save / Reset */}
diff --git a/src/Web/autopilot-monitor-web/app/settings/types.ts b/src/Web/autopilot-monitor-web/app/settings/types.ts
index fd28ddef..83d00904 100644
--- a/src/Web/autopilot-monitor-web/app/settings/types.ts
+++ b/src/Web/autopilot-monitor-web/app/settings/types.ts
@@ -67,6 +67,7 @@ export interface TenantConfiguration {
enableLocalAdminAnalyzer?: boolean;
localAdminAllowedAccountsJson?: string;
enableSoftwareInventoryAnalyzer?: boolean;
+ enableIntegrityBypassAnalyzer?: boolean;
// Bootstrap token
bootstrapTokenEnabled?: boolean;
// Unrestricted mode