Validación dinámica
Cómo se mide el conjunto con el motor YARA y cómo se aíslan reglas problemáticas.
Qué se mide
dynamic_gate.py construye un corpus seguro (ficheros aleatorios, texto, ficheros de sistema y canarios de detección), compila el conjunto aprobado y lo ejecuta con YARA contra cada fichero del corpus midiendo CPU, memoria máxima y tiempo (en Linux con el YARA de Ubuntu; en el job de macOS con el motor que distribuye MacGuard, 4.5.8). Compara el candidato con la release anterior en el mismo job y alternando ejecuciones.
Dibujando el diagrama…
sequenceDiagram
autonumber
participant G as dynamic_gate.py
participant B as bench.py
participant Y as yarac and yara
participant C as compare()
G->>B: build_corpus (random, text, system files, canaries)
loop runs, alternating baseline and candidate
G->>B: measure_set(previous release)
B->>Y: yarac one namespace per file
B->>Y: yara -C per corpus file, timeout 10 s
Y-->>B: cpu, max RSS, wall, exit status
G->>B: measure_set(candidate)
end
G->>C: baseline runs vs candidate runs
alt regression, crash or timeout
C-->>G: verdict regression
G->>G: ddmin over new or changed files
G->>G: culprits to quarantine, rebuild the set
G->>B: measure the reduced set again
else within thresholds
C-->>G: verdict ok
G->>Y: canaries must all be detected
endDescripción del diagrama
dynamic_gate.py construye un corpus seguro con ficheros canario, compila el conjunto aprobado con un espacio de nombres por fichero y mide varias veces la release anterior y el candidato en el mismo job. bench.py ejecuta yara por cada fichero del corpus midiendo con rusage y compare() juzga las medianas frente al ruido de la base. Si aparece un fallo, la depuración por deltas aísla los ficheros nuevos o modificados responsables, se ponen en cuarentena y se mide de nuevo el conjunto reducido.
Código Mermaid
sequenceDiagram
autonumber
participant G as dynamic_gate.py
participant B as bench.py
participant Y as yarac and yara
participant C as compare()
G->>B: build_corpus (random, text, system files, canaries)
loop runs, alternating baseline and candidate
G->>B: measure_set(previous release)
B->>Y: yarac one namespace per file
B->>Y: yara -C per corpus file, timeout 10 s
Y-->>B: cpu, max RSS, wall, exit status
G->>B: measure_set(candidate)
end
G->>C: baseline runs vs candidate runs
alt regression, crash or timeout
C-->>G: verdict regression
G->>G: ddmin over new or changed files
G->>G: culprits to quarantine, rebuild the set
G->>B: measure the reduced set again
else within thresholds
C-->>G: verdict ok
G->>Y: canaries must all be detected
endDecisión
Dibujando el diagrama…
flowchart TD
S["approved set"]:::val --> B{"previous release<br/>available?"}:::val
B -->|no| A["absolute limits<br/>p95, RSS, compile time"]:::val
B -->|yes| CP["compare medians with<br/>the baseline noise"]:::val
A --> V{"ok?"}:::val
CP --> V
V -->|no| I["isolate culprits<br/>delta debugging"]:::qua
I --> Q["culprits to quarantine"]:::qua --> R["rebuild and measure again<br/>max 3 rounds"]:::val --> V
V -->|yes| K{"all canaries detected?<br/>measured set equals set to publish?"}:::gate
K -->|yes| P["publishable"]:::sec
K -->|no| X["not publishable"]:::qua
classDef src fill:#cfe3ff,stroke:#2f6df0,color:#0b1b33
classDef val fill:#ffe9b8,stroke:#b8860b,color:#2b1d00
classDef sec fill:#cdeedd,stroke:#1b6e3c,color:#08210f
classDef pub fill:#e4d7ff,stroke:#6a3fd1,color:#1b0b3b
classDef qua fill:#ffd4cc,stroke:#c0392b,color:#33100b
classDef gate fill:#ffffff,stroke:#111111,stroke-width:3px,color:#111111Descripción del diagrama
La puerta necesita una release anterior con la que comparar. Sin ella aplica límites absolutos de cordura. Una regresión, un crash, un timeout o un conjunto que no compila entero activa el aislamiento de culpables, como máximo tres rondas. Un conjunto que pasa debe además detectar todos los canarios y haber sido medido exactamente como se va a publicar.
Código Mermaid
flowchart TD
S["approved set"]:::val --> B{"previous release<br/>available?"}:::val
B -->|no| A["absolute limits<br/>p95, RSS, compile time"]:::val
B -->|yes| CP["compare medians with<br/>the baseline noise"]:::val
A --> V{"ok?"}:::val
CP --> V
V -->|no| I["isolate culprits<br/>delta debugging"]:::qua
I --> Q["culprits to quarantine"]:::qua --> R["rebuild and measure again<br/>max 3 rounds"]:::val --> V
V -->|yes| K{"all canaries detected?<br/>measured set equals set to publish?"}:::gate
K -->|yes| P["publishable"]:::sec
K -->|no| X["not publishable"]:::qua
classDef src fill:#cfe3ff,stroke:#2f6df0,color:#0b1b33
classDef val fill:#ffe9b8,stroke:#b8860b,color:#2b1d00
classDef sec fill:#cdeedd,stroke:#1b6e3c,color:#08210f
classDef pub fill:#e4d7ff,stroke:#6a3fd1,color:#1b0b3b
classDef qua fill:#ffd4cc,stroke:#c0392b,color:#33100b
classDef gate fill:#ffffff,stroke:#111111,stroke-width:3px,color:#111111- Se mide 5 veces cada conjunto y se comparan medianas contra el ruido de la base; una regresión exige subir más de 3 veces el ruido y como mínimo un 25 %, 0,5 s de CPU o 25 MB.
- Sin release anterior se aplican límites absolutos: p95 de escaneo 2,0 s, 1500 MB de memoria al escanear, 3000 MB al compilar y 240 s de compilación.
- Timeout por fichero: 10 s. Todos los canarios deben detectarse.
- Si algo falla, la depuración por deltas (ddmin) aísla los ficheros nuevos o modificados responsables, se mandan a cuarentena y se vuelve a medir, hasta 3 rondas.
- El conjunto medido debe ser exactamente el que se publica (
set_rootcoincide con la raíz Merkle);publish.ymllo vuelve a comprobar antes de firmar.
En macOS
Un job en un runner macOS instala el motor que se distribuye con MacGuard y ejecuta macguard_smoke.py con el conjunto candidato. Los valores exactos están en config/policy.json.
LÍMITE Los runners de macOS de GitHub son máquinas virtuales (Apple M1 Virtual,hv_vmm_present=1, sin Hypervisor.framework). No hay una máquina virtual macOS independiente:dynamic.jsonlo declara comonot_run: independent-macos-vm. Hace falta un Mac físico propio para eso.
LÍMITE La puerta en Linux usa el YARA de Ubuntu (4.5.0) y la app distribuye 4.5.8. La clasificación estática del conjunto completo dio el mismo resultado con ambos motores (comprobado el 2026-10-18), pero las mediciones dinámicas pueden diferir entre motores y sistemas; ver Límites y pendientes.
No se ejecuta malware real en ningún punto: el corpus se compone de datos sintéticos, texto y ficheros benignos.