Skip to content

Détection — voir, et prouver qu'on voit encore

Machine translation of the French original.

La prévention répond à « peut-on entrer ? ». La détection répond à la question Subsequently, the key date is the one when the first attempt failed: did anyone enter, and what did they do?

This page describes the park's detection mechanisms, the question that each person answers, and, most importantly, how we ensure that they continue to function – because a A malfunctioning detector does not produce an error message; it produces silence, and silence is exactly equivalent to "no signal."

The technical terms refer to the glossary.


One question, one engine

The danger of a set of security tools is to assume that they cover everything. Ten tools that answer the same question leave the other nine questions unanswered. Therefore, the system starts with questions and assigns a dedicated engine to each one.

The Question The Engine Beyond the Question
Does this image contain a known CVE? Trivy What the container does once it's running
Does this code have a vulnerability, a dependency, or a secret? Semgrep, Trivy (dependencies), trufflehog The program's behavior at runtime
Is this host hardened, integrated, and up-to-date? Wazuh — SCA, FIM, rootcheck, vulnerabilities An abnormal behavior, in real-time
What is running autonomously on this machine? osquery (within Wazuh), KnockKnock on macOS —
Does this process do anything unusual? Falco (eBPF) Network traffic
What is traversing the network? Suricata (IDS) The content of an end-to-end encrypted stream
Is this file known malware? ClamAV Newly discovered malware
What is in this file, at all levels? Strelka + YARA What the file would do if executed
Who is attacking the perimeter? CrowdSec + community blocking Anything that is not HTTP
What happened on this machine? Velociraptor — see Response —

The rightmost column is not an admission: it defines where each tool ends. It indicates where its response ends, and therefore where another begins.

The Authority

Trivy has authority over what is built and versioned. Wazuh has authority over the state of a live host. Falco, Suricata and Velociraptor have authority over behavior and flows. None of them duplicate the work of another; when two engines observe the same thing, it is filtered by rule identifier, never disabling either.

flowchart LR
    classDef src fill:#3f3f46,stroke:#3f3f46,color:#fff
    classDef det fill:#7c2d12,stroke:#7c2d12,color:#fff
    classDef hub fill:#0f766e,stroke:#0f766e,color:#fff

    subgraph sources["Ce qu'on observe"]
        img["Images et dépôts"]:::src
        host["Hôtes<br/>fichiers · configuration · paquets"]:::src
        proc["Processus et conteneurs"]:::src
        net["Trafic réseau"]:::src
        file["Fichiers déposés"]:::src
        logs["Journaux du proxy"]:::src
    end

    subgraph moteurs["Les moteurs"]
        trivy["Trivy · Semgrep · trufflehog<br/>scanner de vulnérabilités"]:::det
        wazuh["Wazuh<br/>SIEM · osquery · listes d'IOC"]:::det
        falco["Falco<br/>appels système"]:::det
        suri["Suricata<br/>signatures réseau"]:::det
        av["ClamAV + Strelka<br/>verdict · analyse profonde"]:::det
        cs["CrowdSec<br/>comportement HTTP"]:::det
    end

    tri["Tableau de triage<br/>score · exposition · journal"]:::hub
    hub["Répartiteur d'alertes"]:::hub

    img --> trivy --> tri
    host --> wazuh
    proc --> falco
    net --> suri
    file --> av --> wazuh
    logs --> cs
    wazuh -->|"identifiant de règle"| hub
    falco -.->|"après mesure du bruit"| hub
    suri -.->|"après mesure du bruit"| hub
    cs -->|"403"| logs

Dashed arrows are not just a design detail: they mark engines that collect data before notifying. The reason is deeper, found in the principles.


The SIEM – Wazuh

A SIEM collects logs from the entire environment, correlates them, and alerts. Here, it's Wazuh: a manager and an agent on each machine – hypervisor, container hosts, GPU host, NAS, offsite server, and workstation. A host outside the LAN communicates with the manager via a private mesh, never using a local address that doesn't exist for it.

What the agents provide:

  • File integrity on sensitive paths;
  • Configuration assessment against CIS benchmarks;
  • Rootkit and hidden file/port detection;
  • Vulnerability identification through correlation between installed packages and CVE databases;
  • Hardware, package, and process inventory.

osquery, within the SIEM and not alongside

osquery queries the state of a machine using SQL: services, scheduled tasks, authorized SSH keys, and anything that provides persistence. It is integrated as a module of Wazuh, not as a separate service: two inventories of the same environment will always diverge, and when they do, no one knows which one to trust. The results arrive in the same index as the rest, and a probe verifies that they actually arrive – an active module that sends nothing looks like an active module.

Threat intelligence, consumed

Three lists of IOCs – addresses, domains, and file hashes – are sourced from public sources and refreshed by a scheduled task. Wazuh consults them when an event occurs (CDB lists). The file hash list also draws on what the file system scanners have found: a file detected once is recognized everywhere afterward.

A threat intelligence sharing platform (of the type MISP) was ruled out: it is justified when you produce intelligence, not when you consume three lists. A probe monitors the freshness of the lists – an IOC list that has stopped being updated produces no errors, only missed detections.

Two Alerting Stages

  • Naming rules, one for each detection that you want to receive (a malware found, a canary that no longer responds, a container killed due to lack of memory), each linked to its identifier.
  • A general threshold, for everything that the naming rules do not cover. It is only armed after a period of measurement of the volume it would produce on a healthy system.

Execution – Falco

The SIEM sees the state of a host; it does not see what a program is doing. Without telemetry of system calls, an attacker already present in a container is only visible by what it breaks.

Falco fills this gap on hosts that run containers. The deployment choices, each with its own reason:

Choice Why
Modern eBPF probe, no kernel module Nothing to compile, nothing that breaks on the next kernel update
System package, started before the container engine The first container launched is already being observed
Automatic rule updates from the internet disabled Rules are changed through a repository, read, and never silently
CPU and memory limits A security tool should not be able to compromise the host it protects
Buffer sized for zero burst loss An event lost during a peak is precisely the one we were looking for

In addition to the project's stable rules, there are also custom rules, written for the actions of an attacker on this specific system: writing to a scheduled task or SSH keys, launching a container that mounts the container engine socket without appearing on the list of authorized users, or elevating privileges within a container.

The false positives – the health probes of the databases, which alone generate tens of thousands of events per day – are processed using named exceptions, one for each case, never by disabling a rule.

A rule can load without error and never match

A version upgrade can change the meaning of a field that a rule uses. The rule loads, no errors appear during startup, and it will never trigger again. Reloading the configuration sees nothing wrong: it is correct for the previous version.

This is why the sensor: a probe launches a disposable container, opens a shell within it, and reads a sensitive file, then verifies that both actions have been observed on each host. Its reverse verification involved disabling a rule and observing the probe turn red.


The Network – Suricata

Suricata applies signatures of known attacks to The traffic that passes in front of it. Its output, in JSON, goes to the newspaper search engine.

An IDS only sees what passes in front of it: its location is therefore the real decision. A home mesh network does not offer a mirror port to listen on; the relevant point is where the traffic converges – a virtual network bridge can see both the communication between machines and their output to the Internet, without any additional equipment.

Like Falco, he collects before notifying, and his evidence is a test signature triggered intentionally from a machine, which is then found in the alerts.


The files – two engines, two questions

The architecture of the antivirus chain – a central engine, a signature mirror, and the client that logs – is described in the architecture note. Here, the question is about evidence.

  • ClamAV answers "Is this a known malware?". The file-sharing service refuses to accept a file that has been detected.
  • Strelka answers "What's inside it, at all levels?". It recursively unpacks archives, documents, and embedded objects, and runs dozens of scanners on each piece, including thousands of public YARA rules. It analyzes a selection of paths chosen each night.

The worst failure mode in the park – and why a counter doesn't catch it

YARA compiles its rule set into a single block. A single invalid rule causes the entire game to fail: the container remains healthy, analyses continue, and nothing is detected.

A counter of loaded rules seems sufficient. But it's not: it simply indicates how many rules are in memory, not whether they are still recognizing something. The canary rule is a home-grown rule, placed in the same directory as the others, and re-introduced with each refresh, along with a file designed to trigger it. A probe submits this file and demands detection. If the game no longer compiles, the canary fails along with it – this is exactly what we want.

Reverse verification: a deliberately broken rule file triggers a critical alert, followed by a return to normal.

For ClamAV, the canary is the file EICAR, submitted daily.

A reverse verification should break what it claims to test

To test the EICAR canary, the first idea is to ignore the test signature. It doesn't cause any failure: the engine recognizes the same file under a second signature, which takes over, and the canary remains green. A reverse verification that doesn't cause the canary to fail doesn't prove that the canary is working – it only proves that we haven't been able to make it fail.

What has been ruled out, and why.

  • A dynamic sandbox: The file volume doesn't justify it, and it would add a heavy machine, exposed to hostile code. The question will resurface when a real sample passes both engines.
  • A third YARA rule engine: It would read the same public rule set. Having a second tool that reads the same rules is not a second opinion.

The Perimeter — CrowdSec

CrowdSec reads the logs from the internal proxy, recognizes hostile behavior (scanning, brute-force, known exploits), and enforces its decision through a module integrated into the proxy, which responds with a 403. It also uses a community-shared block list, populated by all installations that share it.

Why in the application layer rather than a firewall: see the architectural note. Its verification ensures that the module actually applies a decision, not just that it is loaded.


Vulnerabilities — the scanner and its axes

A home-built vulnerability scanner aggregates multiple tools and, most importantly, sorts:

Axis Tool What it provides
Images in service, on each container host Trivy Known CVEs, updated daily
Code repositories Trivy (dependencies, IaC) + Semgrep (SAST) Vulnerabilities and dependencies before deployment
Secrets remaining on hosts trufflehog Severity determined by the file's permissions: a secret readable by everyone is more serious than the same secret restricted to its service
Actionability Comparison with upstream image Does a fix already exist?
Exposure Proxy configuration Public, behind the identity provider, or internal
Exploitation EPSS + KEV Likely, or already observed elsewhere

The scoring system crosses severity, exploitation, and exposure: a critical CVE on an internal service comes after a medium CVE, already exploited, on a public service. Each triage decision is recorded with its author.

OpenCVE complements this for anything that isn't a container image – the hypervisor system, the NAS system: it cross-references published CVEs with the versioned inventory of the system's components.

Two additions:

  • An SBOM for each image in service, regenerated weekly. When a new vulnerability is published, the question "Are we affected?" can be answered by checking the inventory, rather than re-running a scan.
  • The time to fix is itself a control. Scanning without measuring the time to fix produces a list that grows. See Compliance.

Hardening, and a second opinion

The SIEM configuration assessment runs continuously. A second tool (Lynis) was run occasionally, for comparison. Where the two disagreed – one module declaring a containment module inactive, the other active – the issue was resolved by a functional test: attempting the action that the module should prevent, and confirming the failure. The automated checks were incorrect.

Rootkit detection tools were not added: they duplicate what the SIEM module already does, and on containerized hosts, they generate noise that would overwhelm the rest.


What these choices have in common

1. Functional tests, not just counters. "The service is running," "5,000 rules loaded," "the agent is connected": these are counters, and a detector can satisfy them all without detecting anything. A functional test injects a known case and demands that it be seen. Each engine on this page has one.

2. Measure the noise before triggering an alert. A new detector first runs in collection-only mode, with a pre-set alert threshold. An alert triggered without prior measurement measures the instrument's rate, not the state of the environment – and an alert that fires every hour from day one would be filtered out before the end of the week.

3. Filter by rule ID, never by group. A group bundles together similar rules that haven't been read. A filter by group creates duplicates; an automated response by group would act on detections that we have never chosen.

4. Exceptions have names. A false positive is handled by a specific exception, tied to its case. Disabling a rule in bulk also disables all the true detections it would have made.

5. One engine per question. Adding a tool is justified by a question without an answer, not by the tool's reputation.


Next to read

Dernière vérification de cette page : 2026-09-11