Diagnóstico y ajuste de alto CPU de Defender
¿Qué problema resuelve este skill?
En máquinas de desarrollo Windows, la protección en tiempo real de Microsoft Defender escanea cada lectura de archivo. Cuando un proceso realiza muchas lecturas (indexación de IDEA, Codex escaneando el proyecto, find / recorriendo todo el disco, Maven descargando dependencias, E/S interna de WSL/Docker), Defender se convierte en una tubería de escaneo sin fin, MsMpEng.exe alcanza 50%+ de CPU y el sistema se vuelve lento.
La idea central de este flujo es: el alto CPU de Defender casi nunca es porque Defender esté dañado, sino porque algún proceso con alta E/S está activando continuamente la protección en tiempo real. Por lo tanto, la clave no es "ajustar los parámetros de Defender", sino localizar la fuente del disparo y eliminarla del camino de escaneo con exclusiones precisas — resolviendo la lentitud sin comprometer la postura de seguridad general.
Flujo de diagnóstico
Paso 0: Confirmar si es Defender y "qué métrica" de CPU
La columna de CPU de procesos en el Administrador de tareas (Task Manager) y el contador de rendimiento \Process(*)\% Processor Time tienen métricas diferentes: el contador puede superar el 100% en máquinas multinúcleo (se acumula 100% por núcleo), mientras que el Administrador de tareas divide el valor del contador por el número de núcleos. Así que "61.2% en el Administrador" podría corresponder a 766% en el contador (máquina de 20 núcleos). Ambos valores son correctos; no uses la métrica equivocada para concluir.
Confirmar rápidamente la ocupación real de MsMpEng (métrica del Administrador de tareas):
$cores = $env:NUMBER_OF_PROCESSORS
$c = (Get-Counter '\Process(MsMpEng*)\% Processor Time').CounterSamples | Where-Object { $_.InstanceName -like 'msmpeng*' } | Select-Object -First 1
"MsMpEng: Contador=$([math]::Round($c.CookedValue,1))% Equiv. Administrador=$([math]::Round($c.CookedValue/$cores,1))% (máquina $cores núcleos)"
Si el Administrador muestra alto pero el contador es consistentemente 0, es un valor obsoleto sin refrescar del Administrador de tareas — simplemente reinícialo, no modifiques Defender.
Paso 1: Localizar la fuente del disparo (por correlación, no intuición)
Las causas raíz del alto CPU de Defender se dividen en tres categorías, con diferentes métodos de localización:
| Causa raíz | Características | Cómo confirmar |
|---|---|---|
| Protección en tiempo real activada por un proceso externo (más común) | CPU de MsMpEng fluctúa en pulsos, hay un proceso externo generando alta E/S al mismo tiempo | Muestreo continuo: encuentra qué proceso tiene E/S alta cuando MsMpEng se dispara |
| Escaneo programado/en segundo plano | CPU sostenida, poca fluctuación; ScanRunning tiene valor o hay tareas programadas activas | Get-MpComputerStatus para ver ScanRunning; Get-ScheduledTask -TaskPath '\Microsoft\Windows\Windows Defender\*' |
| Tarea en segundo plano del propio Defender (verificación tras actualización de definiciones, muestreo en la nube, etc.) | MsMpEng tiene la lectura IO más alta, pero no hay un proceso externo correspondiente con alta E/S | Muestreo: ver si la IO del propio MsMpEng supera con creces a la de otros procesos |
Herramienta de diagnóstico clave: ejecuta scripts/diag-mpcpu.ps1. Muestrea durante varios segundos, registrando simultáneamente el CPU de MsMpEng y los IO Data Bytes/sec de cada proceso. Interpretación:
- Si la IO de un proceso se dispara y MsMpEng también se dispara → ese proceso es la fuente del disparo, ve al Paso 2 para solucionar la causa raíz
- Si MsMpEng tiene la lectura IO más alta y no hay IO externa alta → ve al Paso 3 (tareas en segundo plano/escaneo)
- Si MsMpEng está cerca de 0 durante todo el tiempo → el problema ya no está en Defender, busca en otra parte (el usuario podría estar viendo un valor obsoleto del Administrador de tareas)
Paso 2: Solución de raíz — agregar exclusiones a la fuente del disparo
Hay dos tipos de exclusiones, es importante entender la diferencia:
- Exclusión de proceso (ExclusionProcess): especifica el nombre del proceso (ej.
idea64.exe). Cuando ese proceso lee un archivo, no se activa el escaneo, pero si otro proceso accede al mismo archivo, sí se escanea. Preciso, seguro, úsalo primero. - Exclusión de ruta (ExclusionPath): especifica un directorio; cualquier proceso (incluyendo navegador, EDR) que acceda a archivos en ese directorio no será escaneado. Adecuado para cachés/discos virtuales donde "solo son archivos de datos, nadie debería escanearlos"; no lo uses para excluir directorios de código fuente del proyecto — estos deben protegerse con exclusión de proceso (solo el desarrollador lo lee sin escaneo, pero el navegador descargando al mismo directorio aún se escanearía). Esta es también la razón por la que
gen-exclusions.ps1solo genera rutas de caché/disco virtual/raíz de herramientas, nunca directorios de proyecto.
Por qué priorizar la exclusión de proceso: la exclusión de ruta elimina la protección en tiempo real para todos los procesos que accedan a archivos en ese directorio; la exclusión de proceso solo afecta a una herramienta específica, reduciendo significativamente la superficie de ataque. Por ejemplo, excluir el proceso codex.exe permite que Codex lea tu proyecto sin escaneo, pero si el navegador descarga un archivo al mismo directorio, aún será escaneado — eso es lo que queremos.
Ejecuta scripts/gen-exclusions.ps1 — escanea los procesos de desarrollo en ejecución, los empareja con patrones de herramientas conocidas y genera automáticamente las exclusiones de proceso y ruta recomendadas. Por defecto ejecuta DryRun para previsualizar (muestra sugerencias + justificación), y solo tras confirmar con -Apply escribe en Defender. Es idempotente y hace una copia de seguridad de las exclusiones actuales antes de ejecutarse.
Paso 3: Manejo de causas raíz de escaneo en segundo plano
Si es un escaneo programado / mantenimiento automático en ejecución (ScanRunning tiene valor, tarea programada Estado=Running), normalmente basta con esperar a que termine — no se debe matar forzosamente — Defender está realizando un mantenimiento de seguridad necesario. Si se activa repetidamente en momentos inconvenientes, ajusta el programa:
# Ver escaneos programados
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Windows Defender\*'
# Ajustar hora del escaneo rápido (ejemplo: cada día a las 3 AM) — ten en cuenta que sobrescribe la configuración de escaneo programado existente
Set-MpPreference -ScanScheduleQuickScanTime 03:00:00
Si es una verificación completa tras una actualización de definiciones (ocasional), normalmente es única y termina sola.
Paso 4: Verificación
Después de agregar las exclusiones, vuelve a activar la carga de IO original (reabre el IDE con indexación, vuelve a ejecutar find, deja que Codex escanee el proyecto) y ejecuta de nuevo diag-mpcpu.ps1. El criterio de éxito es: bajo la misma carga de IO, MsMpEng baja de su nivel alto original a cerca de 0. Si no baja, significa que las exclusiones no cubren la verdadera fuente del disparo — vuelve al Paso 1 y mira en la salida del diagnóstico qué proceso sigue disparándose.
Límites de seguridad — lo que nunca se excluye
Las exclusiones reducen la protección en tiempo real para la ruta/proceso correspondiente, por lo que deben tener límites. Lo siguiente nunca debe incluirse en exclusiones, sin importar cuánto "ahorre CPU" (la lista completa y autorizada está en scripts/gen-exclusions.ps1, donde $denyProcs y $denyPathPrefix son la única fuente de verdad; esta documentación es solo explicativa):
- Procesos del sistema:
svchost.exe,dllhost.exe,smartscreen.exe,conhost.exe,lsass.exe,csrss.exe, etc. - Navegadores y sus WebView:
msedge.exe,chrome.exe,msedgewebview2.exe— las descargas de navegadores son la principal puerta de entrada de malware; mantener escaneo - Clientes de seguridad/control: EDR corporativo, clientes VPN (como 深信服 ECAgent, CrowdStrike, SentinelOne) — modificarlos puede generar alertas de cumplimiento y son líneas de defensa
- Directorio de usuario completo / raíz de disco del sistema: granularidad demasiado gruesa, equivalente a estar desprotegido
- Extensiones ejecutables como
*.jar,*.exe,*.dll,*.ps1: son ejecutables; mantener escaneo. Las exclusiones por extensión solo se usan para artefactos de compilación puros (*.class) o registros (*.log) que no son ejecutables
Principio de decisión: las exclusiones deben apuntar a "archivos que una herramienta de desarrollo confiable lee al hacer su trabajo normal", no a "excluir todo para ahorrar CPU".
Diagnóstico avanzado: Performance Recorder
Cuando el script de diagnóstico aún no localiza con precisión, usa el grabador de rendimiento oficial de Defender (requiere administrador) — proporciona un informe preciso de dónde gasta MsMpEng el tiempo en términos de rutas/procesos específicos:
New-MpPerformanceRecord -RecordTo C:\perf.mpdr # Graba 60s (reproduce el alto CPU durante ese tiempo)
# El informe señalará las rutas y procesos que más CPU consumen, para agregar exclusiones precisas basadas en eso
Archivos de referencia
references/common-exclusions.md— lista categorizada de exclusiones recomendadas para herramientas de desarrollo comunes (IDE/Java/Node/WSL/Docker/asistentes de codificación IA/cachés de compilación), con consideraciones de seguridad para cada categoría. Se usa para verificar cobertura al generar exclusiones.scripts/diag-mpcpu.ps1— script de muestreo de diagnósticoscripts/gen-exclusions.ps1— genera y aplica automáticamente exclusiones (previsualización por defecto)