<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nguyen Dong</title>
    <description>The latest articles on DEV Community by Nguyen Dong (@xuxu298).</description>
    <link>https://dev.to/xuxu298</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3810025%2F6d6873c9-b089-4f5b-8872-076d73c641d7.png</url>
      <title>DEV Community: Nguyen Dong</title>
      <link>https://dev.to/xuxu298</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xuxu298"/>
    <language>en</language>
    <item>
      <title>Wazuh FIM "not detecting" a changed file usually means it has not looked yet</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Wed, 07 Oct 2026 03:46:49 +0000</pubDate>
      <link>https://dev.to/xuxu298/wazuh-fim-not-detecting-a-changed-file-usually-means-it-has-not-looked-yet-5d1a</link>
      <guid>https://dev.to/xuxu298/wazuh-fim-not-detecting-a-changed-file-usually-means-it-has-not-looked-yet-5d1a</guid>
      <description>&lt;p&gt;You add a directory to Wazuh file integrity monitoring, change a file, and nothing happens. On Wazuh 4.14.7 the usual reason is the schedule, not a bug. We measured it on a manager container.&lt;/p&gt;

&lt;h2&gt;
  
  
  The defaults
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;syscheck&amp;gt;&lt;/code&gt; block in the 4.14.7 manager image's default &lt;code&gt;ossec.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;frequency&amp;gt;&lt;/span&gt;43200&lt;span class="nt"&gt;&amp;lt;/frequency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;scan_on_start&amp;gt;&lt;/span&gt;yes&lt;span class="nt"&gt;&amp;lt;/scan_on_start&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;alert_new_files&amp;gt;&lt;/span&gt;yes&lt;span class="nt"&gt;&amp;lt;/alert_new_files&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;directories&amp;gt;&lt;/span&gt;/etc,/usr/bin,/usr/sbin&lt;span class="nt"&gt;&amp;lt;/directories&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;directories&amp;gt;&lt;/span&gt;/bin,/sbin,/boot&lt;span class="nt"&gt;&amp;lt;/directories&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;43200&lt;/code&gt; seconds is 12 hours. No directory has &lt;code&gt;realtime&lt;/code&gt; or &lt;code&gt;whodata&lt;/code&gt;. So a changed file is reported at the next scheduled scan, up to 12 hours later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we measured
&lt;/h2&gt;

&lt;p&gt;Two test directories, one plain and one with &lt;code&gt;realtime="yes"&lt;/code&gt;, files changed after the first scan:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What we did&lt;/th&gt;
&lt;th&gt;Alert&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;first scan after start, files already present&lt;/td&gt;
&lt;td&gt;none: the first scan only records a baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;changed a file in the plain directory, default 12 h interval, waited 25 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;none&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;same, with &lt;code&gt;&amp;lt;frequency&amp;gt;60&amp;lt;/frequency&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;rule 550, level 7, mode &lt;code&gt;scheduled&lt;/code&gt;, after about 64 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;changed a file in the &lt;code&gt;realtime&lt;/code&gt; directory&lt;/td&gt;
&lt;td&gt;rule 550, level 7, mode &lt;code&gt;realtime&lt;/code&gt;, within seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;created a new file there&lt;/td&gt;
&lt;td&gt;rule 554, level 5, mode &lt;code&gt;realtime&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to check in a minute
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'(6003)'&lt;/span&gt; /var/ossec/logs/ossec.log | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 20     &lt;span class="c"&gt;# monitored paths and their options&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'\(600[89]\)'&lt;/span&gt; /var/ossec/logs/ossec.log | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 4   &lt;span class="c"&gt;# last scan start (6008) and end (6009)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your path's &lt;code&gt;(6003)&lt;/code&gt; line does not end in &lt;code&gt;realtime&lt;/code&gt; (or &lt;code&gt;whodata&lt;/code&gt;), changes wait for the next scan. If the path is not listed at all, it is not monitored.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Real-time on the paths you would actually act on, on the agent or in the group's &lt;code&gt;agent.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;syscheck&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;directories&lt;/span&gt; &lt;span class="na"&gt;realtime=&lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt; &lt;span class="na"&gt;check_all=&lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/etc/nginx,/var/www/app/config&lt;span class="nt"&gt;&amp;lt;/directories&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/syscheck&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the restart, the &lt;code&gt;(6003)&lt;/code&gt; line for that path ends in &lt;code&gt;realtime&lt;/code&gt;, followed by &lt;code&gt;(6012): Real-time file integrity monitoring started.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keep real-time to small, meaningful directories: real-time on large or busy trees is how FIM turns into noise. And when you test, wait for the &lt;code&gt;(6009)&lt;/code&gt; scan-ended line before changing a file, because changes before the baseline exists are not alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Measured on a Wazuh 4.14.7 manager container, with &lt;code&gt;wazuh-syscheckd&lt;/code&gt; monitoring its own Linux filesystem; agents use the same module, but we did not run a separate agent. Not measured: &lt;code&gt;whodata&lt;/code&gt;, Windows, network shares, inotify limits on very large directories, real-time noise on a busy server.&lt;/p&gt;

&lt;p&gt;Full note: &lt;a href="https://atkvn.com/fix-wazuh-fim-not-detecting-file-changes.html" rel="noopener noreferrer"&gt;https://atkvn.com/fix-wazuh-fim-not-detecting-file-changes.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology. We check and fix Wazuh rules for people who run it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>security</category>
      <category>linux</category>
    </item>
    <item>
      <title>Sophos Firewall logs and Wazuh: the newer syslog layout matches no decoder</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Tue, 06 Oct 2026 05:03:50 +0000</pubDate>
      <link>https://dev.to/xuxu298/--25b7</link>
      <guid>https://dev.to/xuxu298/--25b7</guid>
      <description>&lt;p&gt;Sophos Firewall can send syslog in two layouts. Wazuh 4.14.7 reads one of them. If your firewall uses the other, the logs arrive and nothing alerts, ever. We measured both, and tested two fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two layouts
&lt;/h2&gt;

&lt;p&gt;Sophos's own syslog guide documents both. The legacy one, which Sophos calls &lt;em&gt;Device standard&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;device="SFW" date=2018-05-30 time=13:14:26 timezone="IST" device_name="XG125w" device_id=SFDemo-763180a log_id=010102600002 log_type="Firewall" log_component="Firewall Rule" log_subtype="Denied" status="Deny" ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;em&gt;Central reporting&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;device_name="SFW" timestamp="2023-12-11T09:02:50-0500" device_model="SF01V" device_serial_id="SFDemo-c07-gl-vm-01" log_id="010101600001" log_type="Firewall" log_component="Firewall Rule" log_subtype="Allowed" ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Wazuh does with each
&lt;/h2&gt;

&lt;p&gt;The stock decoder in &lt;code&gt;ruleset/decoders/0510-sophos_fw_decoders.xml&lt;/code&gt; is anchored on the legacy start of line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;prematch&amp;gt;&lt;/span&gt;^device="\w*"\s+date=\d+-\d+-\d+\s+time=&lt;span class="nt"&gt;&amp;lt;/prematch&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We sent a denied-traffic line in each layout over UDP syslog to a Wazuh 4.14.7 manager:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layout&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;legacy (&lt;code&gt;device="SFW" date=…&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;decoded as &lt;code&gt;sophos-fw&lt;/code&gt; → rule 70021, level 5, &lt;em&gt;Traffic Denied&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central reporting (&lt;code&gt;device_name="SFW" timestamp=…&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No decoder matched&lt;/strong&gt; → generic rule 1002, level 2 → no alert&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The stock rules key on the decoded &lt;code&gt;status&lt;/code&gt; field, and the Central reporting layout has no &lt;code&gt;status&lt;/code&gt; at all; it carries &lt;code&gt;log_subtype&lt;/code&gt; instead. So a Central reporting line has neither the decoder nor the field the rules need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 1: send the legacy layout
&lt;/h2&gt;

&lt;p&gt;If your firewall's syslog server settings let you pick the format, choose the device-standard one and the stock decoder and rules apply unchanged. Check first whether anything else reading the same stream expects the new layout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 2: decode the Central reporting layout
&lt;/h2&gt;

&lt;p&gt;A parent decoder anchored on the new start of line, then one child per field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;decoder&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sophos-fw-crf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;prematch&amp;gt;&lt;/span&gt;^device_name="\S+" timestamp="&lt;span class="nt"&gt;&amp;lt;/prematch&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/decoder&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;decoder&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sophos-fw-crf-fields"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;parent&amp;gt;&lt;/span&gt;sophos-fw-crf&lt;span class="nt"&gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;regex&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"pcre2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;log_type="([^"]*)" log_component="([^"]*)" log_subtype="([^"]*)"&lt;span class="nt"&gt;&amp;lt;/regex&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;order&amp;gt;&lt;/span&gt;log_type, log_component, log_subtype&lt;span class="nt"&gt;&amp;lt;/order&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/decoder&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;decoder&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sophos-fw-crf-fields"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;parent&amp;gt;&lt;/span&gt;sophos-fw-crf&lt;span class="nt"&gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;regex&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"pcre2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;\bsrc_ip="([^"]*)"&lt;span class="nt"&gt;&amp;lt;/regex&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;order&amp;gt;&lt;/span&gt;srcip&lt;span class="nt"&gt;&amp;lt;/order&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/decoder&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(and the same pattern for &lt;code&gt;dst_ip&lt;/code&gt;, &lt;code&gt;src_port&lt;/code&gt;, &lt;code&gt;dst_port&lt;/code&gt;, &lt;code&gt;protocol&lt;/code&gt;, &lt;code&gt;fw_rule_id&lt;/code&gt;). Rules on &lt;code&gt;log_type&lt;/code&gt; = &lt;code&gt;Firewall&lt;/code&gt; and &lt;code&gt;log_subtype&lt;/code&gt; = &lt;code&gt;Denied&lt;/code&gt; / &lt;code&gt;Allowed&lt;/code&gt;, plus an 18-in-45-seconds rule with &lt;code&gt;&amp;lt;same_source_ip /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Writing the address as &lt;code&gt;srcip&lt;/code&gt; (the stock decoder uses &lt;code&gt;src_ip&lt;/code&gt;) matters: &lt;code&gt;&amp;lt;same_source_ip&amp;gt;&lt;/code&gt; and the &lt;code&gt;firewall-drop&lt;/code&gt; active response only read &lt;code&gt;srcip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What we measured with it on 4.14.7:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sent&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 Central reporting denied line&lt;/td&gt;
&lt;td&gt;0 alerts&lt;/td&gt;
&lt;td&gt;level 5, srcip/dstip/dstport read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;the same, 18 times in a few seconds&lt;/td&gt;
&lt;td&gt;no alert&lt;/td&gt;
&lt;td&gt;17 × level 5, then the level 10 rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sophos's own &lt;em&gt;Allowed&lt;/em&gt; example&lt;/td&gt;
&lt;td&gt;no decoder&lt;/td&gt;
&lt;td&gt;level 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 legacy denied line&lt;/td&gt;
&lt;td&gt;70021&lt;/td&gt;
&lt;td&gt;70021, untouched&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;wazuh-analysisd -t&lt;/code&gt;: no warnings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Measured on a Wazuh 4.14.7 manager container with syslog over UDP and in &lt;code&gt;wazuh-logtest&lt;/code&gt;. We did not run a Sophos Firewall. The &lt;em&gt;Allowed&lt;/em&gt; line is Sophos's published example; the &lt;em&gt;Denied&lt;/em&gt; lines were written by us in the same layout. The decoder covers firewall-rule events only, not admin login, IPS, web filter or VPN. We have not checked which SFOS release made Central reporting the default, or the exact menu name for the format setting.&lt;/p&gt;

&lt;p&gt;The full decoder and rule files, with the one-minute checks: &lt;a href="https://atkvn.com/fix-sophos-firewall-logs-not-showing-in-wazuh.html" rel="noopener noreferrer"&gt;https://atkvn.com/fix-sophos-firewall-logs-not-showing-in-wazuh.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology. We check and fix Wazuh rules for people who run it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>sophos</category>
      <category>security</category>
    </item>
    <item>
      <title>FortiGate denied traffic never reaches the Wazuh dashboard. Rule 81618 is level 1.</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Mon, 05 Oct 2026 07:02:34 +0000</pubDate>
      <link>https://dev.to/xuxu298/fortigate-denied-traffic-never-reaches-the-wazuh-dashboard-rule-81618-is-level-1-3a2k</link>
      <guid>https://dev.to/xuxu298/fortigate-denied-traffic-never-reaches-the-wazuh-dashboard-rule-81618-is-level-1-3a2k</guid>
      <description>&lt;p&gt;FortiGate sends its logs to Wazuh, failed admin logins show up, and denied traffic does not. On Wazuh 4.14.7 that is the stock ruleset working as written. We measured it, plus a second problem that only shows up with CSV syslog.&lt;/p&gt;

&lt;p&gt;Setup: FortiOS-style key=value lines sent over UDP syslog to a Wazuh 4.14.7 manager container; we read &lt;code&gt;alerts.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 1: every traffic log stops at level 1
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;ruleset/rules/0391-fortigate_rules.xml&lt;/code&gt;, rule &lt;code&gt;81618&lt;/code&gt; matches any FortiGate log with &lt;code&gt;type=traffic&lt;/code&gt; at &lt;strong&gt;level 1&lt;/strong&gt;. It does not look at &lt;code&gt;action&lt;/code&gt;, so denied and allowed sessions land on the same rule. The default &lt;code&gt;&amp;lt;log_alert_level&amp;gt;&lt;/code&gt; in &lt;code&gt;ossec.conf&lt;/code&gt; is &lt;strong&gt;3&lt;/strong&gt;, and nothing below it is written to &lt;code&gt;alerts.json&lt;/code&gt;. The only traffic rule above the line is &lt;code&gt;81619&lt;/code&gt;, level 3, after 18 traffic events from one source within 45 seconds.&lt;/p&gt;

&lt;p&gt;We sent one denied forward session (&lt;code&gt;action="deny"&lt;/code&gt;, SSH from outside to an internal host) and one &lt;em&gt;Admin login failed&lt;/em&gt; event:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;In &lt;code&gt;alerts.json&lt;/code&gt;?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;traffic, &lt;code&gt;action="deny"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;81618&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;admin login failed&lt;/td&gt;
&lt;td&gt;81606&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Reason 2: CSV format corrupts &lt;code&gt;srcip&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The stock decoder reads key=value pairs separated by spaces. In CSV format the separator is a comma, so the capture for &lt;code&gt;srcip&lt;/code&gt; runs to the next space. The same login-failed event in CSV produced an alert whose &lt;code&gt;data.srcip&lt;/code&gt; was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;&lt;span class="mf"&gt;203.0.113.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;dstip&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;192.168.1.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;action&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;status&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule still fires, but GeoIP, &lt;code&gt;&amp;lt;same_source_ip&amp;gt;&lt;/code&gt; correlation and the &lt;code&gt;firewall-drop&lt;/code&gt; active response all read that field.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Send the default format&lt;/strong&gt; for the syslog server Wazuh listens on:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;syslogd&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt;
    &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Raise denied traffic to an alert&lt;/strong&gt; in &lt;code&gt;/var/ossec/etc/rules/local_rules.xml&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"local,fortigate,"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"100210"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if_sid&amp;gt;&lt;/span&gt;81618&lt;span class="nt"&gt;&amp;lt;/if_sid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;action&amp;gt;&lt;/span&gt;deny&lt;span class="nt"&gt;&amp;lt;/action&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;FortiGate: traffic denied by policy.&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;group&amp;gt;&lt;/span&gt;firewall_block,&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On 4.14.7 the same denied line that produced nothing produced a level 5 alert with &lt;code&gt;srcip&lt;/code&gt; and &lt;code&gt;dstport&lt;/code&gt; intact. Narrow it (interface, port, destination) if an internet-facing firewall makes it too loud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use the &lt;code&gt;&amp;lt;action&amp;gt;&lt;/code&gt; tag, not &lt;code&gt;&amp;lt;field name="action"&amp;gt;&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;action&lt;/code&gt; is a static field. With the &lt;code&gt;&amp;lt;field&amp;gt;&lt;/code&gt; form, 4.14.7 logged &lt;code&gt;ERROR: Failure to read rule 100210. Field 'action' is static.&lt;/code&gt; and the manager did not start, so there were no alerts at all, not only for FortiGate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Measured on a Wazuh 4.14.7 manager container (syslog over UDP 514, and &lt;code&gt;wazuh-logtest&lt;/code&gt;). We did not run a FortiGate: the lines were written in the FortiOS key=value layout and converted to CSV by changing the separator. Not measured: &lt;code&gt;cef&lt;/code&gt; and &lt;code&gt;rfc5424&lt;/code&gt; formats, UTM/VPN/IPS logs, other versions. The CLI syntax is from Fortinet's &lt;em&gt;config log syslogd setting&lt;/em&gt; reference, not run on a device.&lt;/p&gt;

&lt;p&gt;Full note with the one-minute checks: &lt;a href="https://atkvn.com/fix-fortigate-logs-not-showing-in-wazuh.html" rel="noopener noreferrer"&gt;https://atkvn.com/fix-fortigate-logs-not-showing-in-wazuh.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology. We check and fix Wazuh rules for people who run it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>fortinet</category>
      <category>security</category>
    </item>
    <item>
      <title>A single pfSense block never becomes a Wazuh alert. Here is why, measured.</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Sun, 04 Oct 2026 01:08:44 +0000</pubDate>
      <link>https://dev.to/xuxu298/a-single-pfsense-block-never-becomes-a-wazuh-alert-here-is-why-measured-563m</link>
      <guid>https://dev.to/xuxu298/a-single-pfsense-block-never-becomes-a-wazuh-alert-here-is-why-measured-563m</guid>
      <description>&lt;p&gt;You point pfSense at Wazuh, the logs arrive, and the dashboard stays empty. Most people assume the integration is broken. On Wazuh 4.14.7 it usually is not: there are two separate reasons, and one of them is by design.&lt;/p&gt;

&lt;p&gt;We sent pfSense &lt;code&gt;filterlog&lt;/code&gt; lines over UDP syslog to a Wazuh 4.14.7 manager container and read &lt;code&gt;archives.log&lt;/code&gt; and &lt;code&gt;alerts.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 1: rule 87701 carries &lt;code&gt;no_log&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The stock pfSense rules live in &lt;code&gt;ruleset/rules/0540-pfsense_rules.xml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Matches&lt;/th&gt;
&lt;th&gt;Becomes an alert?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;87700&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;any &lt;code&gt;filterlog&lt;/code&gt; event decoded as &lt;code&gt;pf&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;no (level 0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;87701&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;action&lt;/code&gt; = block&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;no&lt;/strong&gt;: it has &lt;code&gt;&amp;lt;options&amp;gt;no_log&amp;lt;/options&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;87702&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;18 × 87701 from one source IP within 45 s&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The comment above 87701 says: &lt;em&gt;"We don't log firewall events, because they go to their own log file."&lt;/em&gt; Pass events stop at 87700.&lt;/p&gt;

&lt;p&gt;What we measured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One block line over UDP 514: it reached &lt;code&gt;archives.log&lt;/code&gt;; &lt;code&gt;alerts.json&lt;/code&gt; stayed empty.&lt;/li&gt;
&lt;li&gt;18 block lines from one address within the window: the 18th came back as 87702, level 10.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a working integration shows nothing until one address is blocked 18 times in 45 seconds.&lt;/p&gt;

&lt;p&gt;One trap while testing: &lt;code&gt;wazuh-logtest&lt;/code&gt; prints &lt;em&gt;"Alert to be generated"&lt;/em&gt; for 87701 anyway. Logtest does not apply &lt;code&gt;no_log&lt;/code&gt;. Check &lt;code&gt;alerts.json&lt;/code&gt;, not logtest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reason 2: RFC 5424 lines match no decoder
&lt;/h2&gt;

&lt;p&gt;pfSense can log in BSD (RFC 3164) or RFC 5424 format. The stock decoder is keyed on &lt;code&gt;&amp;lt;program_name&amp;gt;filterlog&amp;lt;/program_name&amp;gt;&lt;/code&gt;, which Wazuh's pre-decoder reads from a BSD-style header. Over UDP on 4.14.7:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line sent&lt;/th&gt;
&lt;th&gt;Decoder&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Oct  2 15:00:01 pfSense filterlog[12345]: 5,,,1000000103,igb1,match,block,…&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pf&lt;/code&gt;: srcip, dstip, action read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2026-10-02T15:00:01.123456+07:00 pfSense.home.arpa filterlog[12345]: …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pf&lt;/code&gt;: read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;134&amp;gt;1 2026-10-02T15:00:01.123456+07:00 pfSense.home.arpa filterlog 12345 - - …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No decoder matched&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With RFC 5424, &lt;code&gt;archives.log&lt;/code&gt; even shows the manager's own host name instead of the firewall's: the header was never parsed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Send BSD format.&lt;/strong&gt; In pfSense, &lt;em&gt;Status → System Logs → Settings&lt;/em&gt;, set the log message format to BSD (RFC 3164).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide which blocks you want as alerts.&lt;/strong&gt; To alert on every block, overwrite 87701 without &lt;code&gt;no_log&lt;/code&gt; in &lt;code&gt;/var/ossec/etc/rules/local_rules.xml&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"local,pfsense,"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"87701"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt; &lt;span class="na"&gt;overwrite=&lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if_sid&amp;gt;&lt;/span&gt;87700&lt;span class="nt"&gt;&amp;lt;/if_sid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;action&amp;gt;&lt;/span&gt;block&lt;span class="nt"&gt;&amp;lt;/action&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;pfSense firewall drop event.&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;group&amp;gt;&lt;/span&gt;firewall_block,pci_dss_1.4,gpg13_4.12,hipaa_164.312.a.1,nist_800_53_SC.7,tsc_CC6.7,tsc_CC6.8,&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On 4.14.7 this loaded with no warnings, and the same single block line that produced nothing produced one 87701 alert. An internet-facing firewall blocks a lot, so many people prefer a narrower child rule (one interface, one port) and leave 87701 alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Measured on a Wazuh 4.14.7 manager container, with syslog over UDP from 127.0.0.1 and in &lt;code&gt;wazuh-logtest&lt;/code&gt;. We did not run a pfSense box: the lines were written in the &lt;code&gt;filterlog&lt;/code&gt; format for one IPv4 TCP block and one pass. Not measured: IPv6, other pfSense programs, OPNsense, other Wazuh versions.&lt;/p&gt;

&lt;p&gt;Full note with the one-minute checks: &lt;a href="https://atkvn.com/fix-pfsense-logs-not-showing-in-wazuh.html" rel="noopener noreferrer"&gt;https://atkvn.com/fix-pfsense-logs-not-showing-in-wazuh.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology. We check and fix Wazuh rules for people who run it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>pfsense</category>
      <category>security</category>
    </item>
    <item>
      <title>Wazuh 5.0 will not load your custom XML rules. 82% of one public pack depends on what it drops.</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Sat, 03 Oct 2026 08:58:04 +0000</pubDate>
      <link>https://dev.to/xuxu298/wazuh-50-will-not-load-your-custom-xml-rules-82-of-one-public-pack-depends-on-what-it-drops-1h01</link>
      <guid>https://dev.to/xuxu298/wazuh-50-will-not-load-your-custom-xml-rules-82-of-one-public-pack-depends-on-what-it-drops-1h01</guid>
      <description>&lt;p&gt;If you run Wazuh 4.x with your own rules and decoders, the 5.0 release changes more than the version number. We read the migration guides that ship with the latest 5.0 pre-release (&lt;code&gt;v5.0.0-beta5&lt;/code&gt;) and ran the numbers on a public community ruleset. Here is what applies to custom content, with the source for each point.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Custom XML files are not loaded at all.&lt;/strong&gt; From &lt;code&gt;docs/guide/migration/manager-configuration-migration.md&lt;/code&gt; at &lt;code&gt;v5.0.0-beta5&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Custom rules and decoders from 4.x &lt;strong&gt;cannot&lt;/strong&gt; be migrated by copying XML files to the manager.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The same table lists &lt;code&gt;&amp;lt;ruleset&amp;gt;&lt;/code&gt; as a &lt;strong&gt;startup error&lt;/strong&gt; and says &lt;code&gt;etc/rules/&lt;/code&gt;, &lt;code&gt;etc/decoders/&lt;/code&gt; and &lt;code&gt;etc/lists/&lt;/code&gt; "do not exist in 5.0". Decoders become YAML assets run by the new engine; rules become Sigma-style YAML documents stored in the indexer and managed through its content API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is no converter.&lt;/strong&gt; From &lt;code&gt;docs/guide/migration/rules-4x-to-5x.md&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is no automatic conversion tool. Rules must be manually rewritten following this guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The manager migration issue (#39109, closed 28 September) states the scope plainly: "rules, decoders, CDB lists and anything the engine changed structurally" are out of scope, and "the translation is the user's responsibility". The tool merged for it (PR #39197) moves agent keys, groups and API users, not content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rules no longer chain.&lt;/strong&gt; The rules guide marks these as not supported:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;4.x&lt;/th&gt;
&lt;th&gt;5.0 (per the guide)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;if_sid&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;if_group&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;if_level&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;not supported; "rules are self-contained"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;if_matched_sid&amp;gt;&lt;/code&gt;, &lt;code&gt;frequency&lt;/code&gt;/&lt;code&gt;timeframe&lt;/code&gt;, &lt;code&gt;&amp;lt;same_*&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;different_*&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;if_fts&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;not supported in rules; "correlation handled separately"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;list&amp;gt;&lt;/code&gt; (CDB lookups)&lt;/td&gt;
&lt;td&gt;not supported in rules; move to KVDBs at the decoder level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;weekday&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;check_diff&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;options&amp;gt;&lt;/code&gt; (&lt;code&gt;no_log&lt;/code&gt;, &lt;code&gt;no_full_log&lt;/code&gt;, …), &lt;code&gt;&amp;lt;var&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;no direct equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And &lt;code&gt;&amp;lt;match&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;regex&amp;gt;&lt;/code&gt; no longer search the raw log: 5.0 rules match fields of the normalized event, with &lt;code&gt;event.original&lt;/code&gt; as the fallback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decoders lose some elements.&lt;/strong&gt; The decoder guide lists &lt;code&gt;&amp;lt;plugin_decoder&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;accumulate/&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;fts&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;json_null_field&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;type&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;use_own_name&amp;gt;&lt;/code&gt; and the &lt;code&gt;pcre2&lt;/code&gt;/&lt;code&gt;offset&lt;/code&gt; options as unsupported: 5.0 parses with its own field-extraction language, not regex.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much of a real ruleset is affected
&lt;/h2&gt;

&lt;p&gt;We took the public SOCFortress &lt;code&gt;Wazuh-Rules&lt;/code&gt; set (75 XML files, 2,211 rules, 105 decoders) and counted, rule by rule, the elements the 5.0 guide marks as unsupported:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Rules&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Use rule chaining (&lt;code&gt;if_sid&lt;/code&gt;, &lt;code&gt;if_group&lt;/code&gt; or &lt;code&gt;if_level&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;1,804&lt;/td&gt;
&lt;td&gt;82%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use correlation (&lt;code&gt;frequency&lt;/code&gt;, &lt;code&gt;if_matched_*&lt;/code&gt;, &lt;code&gt;same_*&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&amp;lt;1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use CDB lookups or &lt;code&gt;check_diff&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&amp;lt;1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;None of the above (only a rewrite to the new format)&lt;/td&gt;
&lt;td&gt;399&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Chaining is how most 4.x content is written: a child rule refines a stock parent. In 5.0 each of those rules has to carry its own full condition, written against normalized field names instead of a parent's decoded fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where things stand
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;v5.0.0-beta5&lt;/code&gt; (1 September) is the latest 5.0 tag. The &lt;code&gt;5.0.0&lt;/code&gt; branch already reads &lt;code&gt;"stage": "rc1"&lt;/code&gt;. No GA date has been announced.&lt;/li&gt;
&lt;li&gt;There is no in-place upgrade from a 4.x manager; the configuration guide says 5.0 is a fresh install.&lt;/li&gt;
&lt;li&gt;Until you move, 4.x keeps loading XML as before, including its quirks: if you are still writing 4.x rules, check them before restarting (one quirk we measured: &lt;a href="https://dev.to/xuxu298/wazuh-analysisd-shows-at-most-50-load-warnings-the-rest-of-your-ignored-rules-are-silent-68i"&gt;wazuh-analysisd shows at most 50 load warnings&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Measure your own
&lt;/h2&gt;

&lt;p&gt;The free checker at &lt;a href="https://atkvn.com/wazuh-rule-precheck.html" rel="noopener noreferrer"&gt;https://atkvn.com/wazuh-rule-precheck.html&lt;/a&gt; runs in the browser and checks 4.x load problems. The counts above came from the same code with a 5.0 mode that lists, per rule, the elements the 5.0 guide marks as unsupported. If you want that list for your own rules before planning a move, send them and your Wazuh version to the address on the checker page and we will send it back, free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Everything about 5.0 here comes from the migration guides at &lt;code&gt;v5.0.0-beta5&lt;/code&gt; and the linked issue and PR, not from running a 5.0 engine. A pre-release can change before GA. The counts are a static reading of the XML.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology. We check and fix Wazuh rules for people who run it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>security</category>
    </item>
    <item>
      <title>wazuh-analysisd shows at most 50 load warnings. The rest of your ignored rules are silent.</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Fri, 02 Oct 2026 09:57:22 +0000</pubDate>
      <link>https://dev.to/xuxu298/wazuh-analysisd-shows-at-most-50-load-warnings-the-rest-of-your-ignored-rules-are-silent-68i</link>
      <guid>https://dev.to/xuxu298/wazuh-analysisd-shows-at-most-50-load-warnings-the-rest-of-your-ignored-rules-are-silent-68i</guid>
      <description>&lt;p&gt;If you load a large set of custom Wazuh rules, &lt;code&gt;wazuh-analysisd -t&lt;/code&gt; and &lt;code&gt;ossec.log&lt;/code&gt; can tell you that some of them will be ignored. What they don't tell you is that they stop counting at 50 messages. On Wazuh 4.14.7, anything beyond that is dropped, oldest first, with no line anywhere.&lt;/p&gt;

&lt;p&gt;We measured it, found where it comes from in the source, and checked a public community ruleset.&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurement
&lt;/h2&gt;

&lt;p&gt;One file, &lt;code&gt;etc/rules/local_rules.xml&lt;/code&gt;, with 60 rules. Each one has an &lt;code&gt;if_sid&lt;/code&gt; pointing at an ID that does not exist, so Wazuh must ignore all 60. Each ignored rule produces two warnings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: (7617): Signature ID '990000' was not found and will be ignored in the 'if_sid' option of rule '100800'.
WARNING: (7619): Empty 'if_sid' value. Rule '100800' will be ignored.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is 120 warnings. Here is what Wazuh 4.14.7 actually printed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;Warnings printed&lt;/th&gt;
&lt;th&gt;Rules named&lt;/th&gt;
&lt;th&gt;Rules never mentioned&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wazuh-analysisd -t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50 (25 × 7617, 25 × 7619)&lt;/td&gt;
&lt;td&gt;100835 to 100859&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100800 to 100834 (35 rules)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ossec.log&lt;/code&gt; at a real start&lt;/td&gt;
&lt;td&gt;starts at 100835&lt;/td&gt;
&lt;td&gt;100835 to 100859&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100800 to 100834&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last 25 rules are reported. The first 35 are ignored exactly the same way, and nothing says so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the 50 comes from
&lt;/h2&gt;

&lt;p&gt;In the 4.14.7 source, the load messages go into a list created with a size limit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/analysisd/logmsg.h&lt;/span&gt;
&lt;span class="cp"&gt;#define ERRORLIST_MAXSIZE   50 ///&amp;lt; Max size of log messages list
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;analysisd.c&lt;/code&gt; and &lt;code&gt;testrule.c&lt;/code&gt; call &lt;code&gt;OSList_SetMaxSize(list_msg, ERRORLIST_MAXSIZE)&lt;/code&gt;, and &lt;code&gt;OSList_AddData&lt;/code&gt; in &lt;code&gt;src/shared/list_op.c&lt;/code&gt; removes the first node when the list grows past its maximum. So the list keeps the newest 50 messages and silently drops the rest.&lt;/p&gt;

&lt;p&gt;That design is reasonable for a log. It is a problem when the log is the only place you learn that a rule you wrote will never fire.&lt;/p&gt;

&lt;h2&gt;
  
  
  On a real ruleset
&lt;/h2&gt;

&lt;p&gt;We loaded the public SOCFortress &lt;code&gt;Wazuh-Rules&lt;/code&gt; set (69 rule files, 6 decoder files) into a clean 4.14.7 manager. &lt;code&gt;wazuh-analysisd -t&lt;/code&gt; printed 52 warnings about ignored rules (50 × &lt;code&gt;7610&lt;/code&gt; for a missing &lt;code&gt;if_group&lt;/code&gt;, one &lt;code&gt;7617&lt;/code&gt;/&lt;code&gt;7619&lt;/code&gt; pair). A static check of the same files found 55. The three extra rules, 900123 to 900125, have the same missing &lt;code&gt;if_group&lt;/code&gt; as the 50 that were reported. They fell off the front of the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a rule gets ignored in the first place
&lt;/h2&gt;

&lt;p&gt;Missing parents are not only typos. Wazuh loads the stock rule files and your files from &lt;code&gt;etc/rules&lt;/code&gt; together, &lt;strong&gt;sorted by file name&lt;/strong&gt;, and a rule's &lt;code&gt;if_sid&lt;/code&gt; must already be loaded when the rule is read. So this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- etc/rules/0010-my_rules.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"local,"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"100714"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"9"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if_sid&amp;gt;&lt;/span&gt;5715&lt;span class="nt"&gt;&amp;lt;/if_sid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;match&amp;gt;&lt;/span&gt;Accepted&lt;span class="nt"&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is ignored on 4.14.7, because &lt;code&gt;0010-my_rules.xml&lt;/code&gt; sorts before &lt;code&gt;0095-sshd_rules.xml&lt;/code&gt;, where 5715 lives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: (7617): Signature ID '5715' was not found and will be ignored in the 'if_sid' option of rule '100714'.
WARNING: (7619): Empty 'if_sid' value. Rule '100714' will be ignored.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;wazuh-analysisd -t&lt;/code&gt; still exits 0. The manager starts. The rule never fires. Rename the file to something that sorts after the parent (&lt;code&gt;local_rules.xml&lt;/code&gt; does) and it loads. The same applies inside one file: a child above its parent is ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check without trusting the 50 lines
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check in small batches.&lt;/strong&gt; Test one custom file at a time with &lt;code&gt;wazuh-analysisd -t&lt;/code&gt;, so no single run produces more than 50 messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count, don't scan.&lt;/strong&gt; For each custom rule ID you expect, confirm it is not named in a &lt;code&gt;will be ignored&lt;/code&gt; line, and treat a run that printed exactly 50 load warnings as incomplete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check statically before you restart.&lt;/strong&gt; We built a free checker that runs in the browser and reports every predicted &lt;code&gt;7610&lt;/code&gt;, &lt;code&gt;7612&lt;/code&gt;, &lt;code&gt;7613&lt;/code&gt;, &lt;code&gt;7617&lt;/code&gt;/&lt;code&gt;7619&lt;/code&gt; and &lt;code&gt;7620&lt;/code&gt;, plus the mistakes that stop the manager (static fields used as &lt;code&gt;&amp;lt;field name="srcip"&amp;gt;&lt;/code&gt;, broken XML, missing decoder parents). It was calibrated case by case against &lt;code&gt;wazuh-analysisd -t&lt;/code&gt; 4.14.7 (15 of 15) and does not upload anything: &lt;a href="https://atkvn.com/wazuh-rule-precheck.html" rel="noopener noreferrer"&gt;https://atkvn.com/wazuh-rule-precheck.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Measured on Wazuh 4.14.7 manager containers. We did not test other versions. The checker only sees the files you give it and the stock 4.14.7 ruleset; it does not run your rules against events.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology. We check and fix Wazuh rules for people who run it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>security</category>
    </item>
    <item>
      <title>Three reasons a custom Wazuh rule stays silent after a clean config check, measured on 4.14.7</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Thu, 01 Oct 2026 14:59:26 +0000</pubDate>
      <link>https://dev.to/xuxu298/three-reasons-a-custom-wazuh-rule-stays-silent-after-a-clean-config-check-measured-on-4147-5a2o</link>
      <guid>https://dev.to/xuxu298/three-reasons-a-custom-wazuh-rule-stays-silent-after-a-clean-config-check-measured-on-4147-5a2o</guid>
      <description>&lt;p&gt;A custom Wazuh rule that never fires rarely has a broken regex. In our lab the usual story is quieter: &lt;code&gt;wazuh-analysisd -t&lt;/code&gt; exits 0, the manager restarts cleanly, and the rule still never produces an alert.&lt;/p&gt;

&lt;p&gt;We measured three ways this happens on Wazuh 4.14.7. None of them is visible from the exit code of the config check.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Wazuh dropped the rule while loading it
&lt;/h2&gt;

&lt;p&gt;If a rule's &lt;code&gt;if_sid&lt;/code&gt; parent does not exist at the moment the rule is read, Wazuh ignores the rule, prints two warnings, and carries on. We wrote up the file-name case &lt;a href="https://dev.to/xuxu298/wazuh-custom-rule-never-fires-and-analysisd-t-still-exits-0-the-file-name-decides-58od"&gt;in an earlier post&lt;/a&gt;: a child of &lt;code&gt;5715&lt;/code&gt; in &lt;code&gt;0094-test.xml&lt;/code&gt; is dropped, the same rule in &lt;code&gt;0096-test.xml&lt;/code&gt; fires.&lt;/p&gt;

&lt;p&gt;This week someone running Wazuh in production described two cases that happen inside a single file, so we measured those too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"test,"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- case A: the parent is defined later in the same file --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"999910"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if_sid&amp;gt;&lt;/span&gt;999911&lt;span class="nt"&gt;&amp;lt;/if_sid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;match&amp;gt;&lt;/span&gt;RDTEST_FWD_CHILD&lt;span class="nt"&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;child, written before its parent&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"999911"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;match&amp;gt;&lt;/span&gt;RDTEST_FWD&lt;span class="nt"&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;parent&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- case B: if_sid points to the rule itself --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"999920"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if_sid&amp;gt;&lt;/span&gt;999920&lt;span class="nt"&gt;&amp;lt;/if_sid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;match&amp;gt;&lt;/span&gt;RDTEST_SELF&lt;span class="nt"&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;self-reference&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;case&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;-t&lt;/code&gt; exit&lt;/th&gt;
&lt;th&gt;warnings&lt;/th&gt;
&lt;th&gt;renamed to &lt;code&gt;9999_...xml&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;logtest and live events&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A: parent later in the same file&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;7617 + 7619 for &lt;code&gt;999910&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;same result&lt;/td&gt;
&lt;td&gt;only the parent &lt;code&gt;999911&lt;/code&gt; matched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B: &lt;code&gt;if_sid&lt;/code&gt; points to itself&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;7617 + 7619 for &lt;code&gt;999920&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;same result&lt;/td&gt;
&lt;td&gt;the rule never fired&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The warnings for case A, word for word:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: (7617): Signature ID '999911' was not found and will be ignored in the 'if_sid' option of rule '999910'.
WARNING: (7619): Empty 'if_sid' value. Rule '999910' will be ignored.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule count agrees. Our test files held 7 rules in total: the three above and four others that load normally. With them in place the manager logged &lt;code&gt;Total rules enabled: '8468'&lt;/code&gt;; after we removed them, &lt;code&gt;'8463'&lt;/code&gt;. That is 5 more, not 7: the 2 missing are &lt;code&gt;999910&lt;/code&gt; and &lt;code&gt;999920&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Renaming the file so it loads last does not help here, because the problem is not the order between files. Wazuh reads a file top to bottom, so a parent must come before its children in the same file, and a rule cannot be its own parent.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A sibling rule takes the event
&lt;/h2&gt;

&lt;p&gt;Rules that hang off the same parent are tried in order of level, highest first. "Hang off" includes more than &lt;code&gt;if_sid&lt;/code&gt;: the stock rule &lt;code&gt;40112&lt;/code&gt; (level 12, failures followed by a success) is attached to &lt;code&gt;5715&lt;/code&gt; through &lt;code&gt;&amp;lt;if_group&amp;gt;authentication_success&amp;lt;/if_group&amp;gt;&lt;/code&gt;, a group that &lt;code&gt;5715&lt;/code&gt; carries. We put one child of the stock sshd rule &lt;code&gt;5715&lt;/code&gt; in &lt;code&gt;local_rules.xml&lt;/code&gt; (&lt;code&gt;&amp;lt;if_sid&amp;gt;5715&amp;lt;/if_sid&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;match&amp;gt;Accepted password&amp;lt;/match&amp;gt;&lt;/code&gt;) and sent two sequences through &lt;code&gt;wazuh-logtest&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S1: one &lt;code&gt;Accepted password&lt;/code&gt; line on its own&lt;/li&gt;
&lt;li&gt;S2: eight &lt;code&gt;Failed password&lt;/code&gt; lines from the same IP within eight seconds, then the same &lt;code&gt;Accepted password&lt;/code&gt; line&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;our rule&lt;/th&gt;
&lt;th&gt;&lt;code&gt;-t&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;S1 lands on&lt;/th&gt;
&lt;th&gt;S2 lands on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;level 9&lt;/td&gt;
&lt;td&gt;exit 0, no warnings&lt;/td&gt;
&lt;td&gt;ours&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;40112&lt;/code&gt; (level 12), ours loses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;level 13&lt;/td&gt;
&lt;td&gt;exit 0, no warnings&lt;/td&gt;
&lt;td&gt;ours&lt;/td&gt;
&lt;td&gt;ours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The rule and the parent are the same in both rows. Only the level changed, and that decided who got the event after a burst of failures. &lt;code&gt;-t&lt;/code&gt; said nothing in either case, because nothing is wrong with the rule. It loaded, and a sibling won.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. It passes logtest because logtest saw one line
&lt;/h2&gt;

&lt;p&gt;One line through &lt;code&gt;wazuh-logtest&lt;/code&gt; tests a decoder and a match. It does not test what happened before that line. We measured three things a one-line test cannot show.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Counting.&lt;/strong&gt; A composite rule with &lt;code&gt;&amp;lt;if_matched_sid&amp;gt;&lt;/code&gt; and &lt;code&gt;frequency="5" timeframe="60"&lt;/code&gt;, fed twelve matching events in one logtest session, fired on the 5th and the 10th. The 6th did not fire again: after an alert the count starts from zero. With &lt;code&gt;&amp;lt;same_source_ip/&amp;gt;&lt;/code&gt;, events from two IPs alternating fired on the 9th and 10th event, the 5th from each IP. Each IP is counted on its own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restarts.&lt;/strong&gt; Rule changes are usually applied with a manager restart, and a restart resets these counts. With &lt;code&gt;frequency="4"&lt;/code&gt; on real log lines read by logcollector: 2 failures, restart, 2 more failures gave no alert. All 4 events reached the manager; the count simply began again after the restart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Events that never arrive.&lt;/strong&gt; Logtest only sees what you paste into it. On a real manager, events can be lost before analysis. We flooded one agent with 900,000 lines with its client buffer turned off. 57,047 arrived, and about 94% were lost at the agent, with one warning in the agent's own &lt;code&gt;ossec.log&lt;/code&gt; as the only trace. &lt;a href="https://dev.to/xuxu298/wazuh-loses-events-three-ways-under-load-and-only-one-of-them-raises-an-alert-1cpd"&gt;Full write-up&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check yours
&lt;/h2&gt;

&lt;p&gt;Rules dropped at load, before a restart (read the output, not the exit code):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/var/ossec/bin/wazuh-analysisd &lt;span class="nt"&gt;-t&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'\((7617|7619)\)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a restart, the same warnings are in the manager log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'\((7617|7619)\)'&lt;/span&gt; /var/ossec/logs/ossec.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every rule id in a 7619 line is a rule that is not running.&lt;/p&gt;

&lt;p&gt;Siblings that might take your event. Look up the parent's groups, then list the rules attached to the parent by id or by one of those groups, and compare levels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="nt"&gt;-A8&lt;/span&gt; &lt;span class="s1"&gt;'id="5715"'&lt;/span&gt; /var/ossec/ruleset/rules | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;group&amp;gt;'&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rnE&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;if_sid&amp;gt;([^&amp;lt;]*[ ,])?5715([ ,][^&amp;lt;]*)?&amp;lt;/if_sid&amp;gt;|&amp;lt;if_group&amp;gt;authentication_success&amp;lt;/if_group&amp;gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /var/ossec/ruleset/rules /var/ossec/etc/rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;5715&lt;/code&gt; and &lt;code&gt;authentication_success&lt;/code&gt; with your rule's parent and its groups. On our 4.14.7 lab the second command prints six lines for &lt;code&gt;5715&lt;/code&gt;, including &lt;code&gt;40112&lt;/code&gt; at line 102 of &lt;code&gt;0280-attack_rules.xml&lt;/code&gt;. A sibling at a higher level that also matches your event will win it.&lt;/p&gt;

&lt;p&gt;Sequences, not lines. Paste the real sequence into one &lt;code&gt;wazuh-logtest&lt;/code&gt; session (the failures and then the success, or the five events a composite rule needs), not only the last line.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we did not measure
&lt;/h2&gt;

&lt;p&gt;One version (4.14.7), a single-node manager, and mostly &lt;code&gt;if_sid&lt;/code&gt;. Not measured: &lt;code&gt;if_group&lt;/code&gt;, decoders, clusters, reloading rules through the API, or how often restarts happen on a real system. The logtest counts in reason 3 come from one session per case. The flood numbers come from one agent reading a file, not syslog over the network.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Free: &lt;a href="https://github.com/xuxu298/rule-doctor-lite" rel="noopener noreferrer"&gt;Rule Doctor Lite&lt;/a&gt;, a read-only script that lists the custom rules that never fired and the likely reason. Run after a restart, it reads the 7617/7619 warnings in &lt;code&gt;ossec.log&lt;/code&gt;, and on our lab it flagged both in-file cases above.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If a rule loads and never fires and you would rather not dig into it yourself, send us the rule, your Wazuh version and a sample event: we find why, then write and test the fix on that version. USD 490 per rule case, paid only after it runs clean on your side. &lt;a href="https://vct.atkvn.com/#fix-pack" rel="noopener noreferrer"&gt;vct.atkvn.com/#fix-pack&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>detectionengineering</category>
      <category>security</category>
      <category>linux</category>
    </item>
    <item>
      <title>Hybrid post-quantum key exchange at the front door went from 50% to 86%. It says nothing about your VPN.</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Wed, 30 Sep 2026 13:04:27 +0000</pubDate>
      <link>https://dev.to/xuxu298/hybrid-post-quantum-key-exchange-at-the-front-door-went-from-50-to-86-it-says-nothing-about-your-3cp1</link>
      <guid>https://dev.to/xuxu298/hybrid-post-quantum-key-exchange-at-the-front-door-went-from-50-to-86-it-says-nothing-about-your-3cp1</guid>
      <description>&lt;p&gt;We run a small public index of post-quantum adoption: one TLS 1.3 handshake per host, against the same list of 350 public front doors, repeated over time. Three runs so far, April, May and September 2026.&lt;/p&gt;

&lt;p&gt;On the 293 hosts that answered in every run:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;April&lt;/th&gt;
&lt;th&gt;May&lt;/th&gt;
&lt;th&gt;September&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;hybrid post-quantum key exchange&lt;/td&gt;
&lt;td&gt;50.2%&lt;/td&gt;
&lt;td&gt;51.2%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;86.0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;105 hosts moved from classical to hybrid (X25519MLKEM768). Across all three runs, &lt;strong&gt;zero moved back&lt;/strong&gt;. Banking moved the furthest of any sector, 28.0% to 94.0% on 50 hosts. A re-run on 14 September reproduced the cohort (293) and the headline (252 of 293) exactly.&lt;/p&gt;

&lt;p&gt;That is real movement. It is also a much narrower fact than it sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the number measures
&lt;/h2&gt;

&lt;p&gt;One handshake, from outside, to one public hostname. It tells you what the internet-facing TLS terminator of that host negotiates today with a client that offers a hybrid group.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it cannot see
&lt;/h2&gt;

&lt;p&gt;Everything behind that terminator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPN.&lt;/strong&gt; IPsec, OpenVPN and WireGuard tunnels negotiate their own keys. A hybrid front door says nothing about them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal TLS.&lt;/strong&gt; Service-to-service traffic, load balancer to backend, database connections. Often older libraries, often pinned versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH.&lt;/strong&gt; Its key exchange is configured separately on every server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signatures and certificates.&lt;/strong&gt; In a 40-host run on 1 September (16 banks plus internet infrastructure and a control group), &lt;strong&gt;0 of 40&lt;/strong&gt; carried a post-quantum signature. That is expected: &lt;strong&gt;no public CA can issue one yet.&lt;/strong&gt; Key exchange is migrating; authentication is not, in any sample we have run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code.&lt;/strong&gt; Hard-coded RSA or ECDH in your own applications doesn't change when a vendor updates a default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traffic already recorded.&lt;/strong&gt; A front door that went hybrid in August protects sessions from August on, not the ones before.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The index says this about itself, and it is worth repeating: a front door isn't an estate, and a vendor default isn't a migration programme. We also do not know what changed over the northern summer, and we don't guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with it
&lt;/h2&gt;

&lt;p&gt;If your public front door already negotiates hybrid, good, and that is probably not where your exposure is. The questions that matter are the ones the index cannot answer from outside:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which of your tunnels, internal links and SSH servers still negotiate classical-only key exchange?&lt;/li&gt;
&lt;li&gt;Which data crossing them has to stay confidential for longer than your migration plan takes?&lt;/li&gt;
&lt;li&gt;Where is classical crypto hard-coded, so a library update won't fix it?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those need a look inside the estate: TLS and server configs, SSH, VPN configs, certificates, code, and, if you can share one, a packet capture, which shows exposure per flow rather than per host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits of the numbers above
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;57 of the 350 hosts did not answer in every run; they are the weakest part of the dataset, and every percentage above is on the 293 that did.&lt;/li&gt;
&lt;li&gt;Public front doors only, one handshake per host, no retries. It measures what a host negotiates, not what it could negotiate with a different client.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Two ways we can help. **PQ Front Door Check&lt;/em&gt;&lt;em&gt;, free: send one hostname you own and we send back one page on what it negotiates. **PQC Readiness Audit&lt;/em&gt;&lt;em&gt;, USD 4,900: the inside view above, across seven surfaces (TLS, server config, SSH, VPN, certificates, code, packet capture), with no agent on your systems. Message Dong Nguyen on LinkedIn.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cryptography</category>
      <category>postquantum</category>
      <category>tls</category>
      <category>security</category>
    </item>
    <item>
      <title>Wazuh loses events three ways under load, and only one of them raises an alert</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Mon, 28 Sep 2026 13:01:05 +0000</pubDate>
      <link>https://dev.to/xuxu298/wazuh-loses-events-three-ways-under-load-and-only-one-of-them-raises-an-alert-1cpd</link>
      <guid>https://dev.to/xuxu298/wazuh-loses-events-three-ways-under-load-and-only-one-of-them-raises-an-alert-1cpd</guid>
      <description>&lt;p&gt;A question we got on LinkedIn: one Wazuh agent reads the logs of 1,600 firewalls, the dashboard shows gaps, and nothing fired. No rule, no alarm. Is that possible?&lt;/p&gt;

&lt;p&gt;It is. We flooded a Wazuh 4.14.7 setup three different ways and counted what arrived, what was dropped, and which of the stock "agent buffer" rules fired.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stock rules you would expect to fire
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;0016-wazuh_rules.xml&lt;/code&gt; (4.14.7), rule &lt;code&gt;201&lt;/code&gt; is the level 0 parent for &lt;code&gt;wazuh: Agent buffer:&lt;/code&gt; messages, with these children:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;rule&lt;/th&gt;
&lt;th&gt;level&lt;/th&gt;
&lt;th&gt;meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;202&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;agent queue is X% full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;203&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;agent queue is full, events may be lost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;204&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;agent queue is flooded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;205&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;back to normal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The default &lt;code&gt;log_alert_level&lt;/code&gt; is 3, so all four are high enough to become alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we measured
&lt;/h2&gt;

&lt;p&gt;Throwaway containers, &lt;code&gt;wazuh-manager:4.14.7&lt;/code&gt; and &lt;code&gt;wazuh-agent:4.14.7&lt;/code&gt; on an internal network, no indexer: we read &lt;code&gt;alerts.json&lt;/code&gt;, &lt;code&gt;archives.json&lt;/code&gt;, &lt;code&gt;ossec.log&lt;/code&gt; and the state files directly. The agent read one syslog-style file with fake lines from 1,600 "firewalls", each tagged so we could count them. A sanity run of 3 lines gave 3 of 3 in both &lt;code&gt;alerts.json&lt;/code&gt; and &lt;code&gt;archives.json&lt;/code&gt;, so zero below means zero.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;case&lt;/th&gt;
&lt;th&gt;setup&lt;/th&gt;
&lt;th&gt;sent&lt;/th&gt;
&lt;th&gt;reached the manager&lt;/th&gt;
&lt;th&gt;buffer alerts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;agent defaults (client buffer on, 500 EPS)&lt;/td&gt;
&lt;td&gt;900,000 lines at 10,000/s for 90 s&lt;/td&gt;
&lt;td&gt;45,493 (5%)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;202&lt;/code&gt; ×1, &lt;code&gt;203&lt;/code&gt; ×44, &lt;code&gt;205&lt;/code&gt; ×1, &lt;strong&gt;&lt;code&gt;204&lt;/code&gt; ×0&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;client buffer &lt;strong&gt;disabled&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;same&lt;/td&gt;
&lt;td&gt;57,047 (6.3%)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;none&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;manager overloaded (&lt;code&gt;&amp;lt;limits&amp;gt;&amp;lt;eps&amp;gt;&lt;/code&gt; at 100), manager reads the file itself&lt;/td&gt;
&lt;td&gt;120,000 at 2,000/s for 60 s&lt;/td&gt;
&lt;td&gt;22,391 (18.7%)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;none&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Case 1 is the only loss path with an alarm. The client buffer drops what exceeds its rate (500 EPS over about 91 seconds matches the 45,493 that arrived), and &lt;code&gt;203&lt;/code&gt; fires every couple of seconds while it happens. But &lt;code&gt;204&lt;/code&gt;, the level 12 "flooded" rule, did not fire once in 90 seconds of a full buffer.&lt;/p&gt;

&lt;p&gt;Case 2 lost 842,953 lines at the agent's internal queue between logcollector and the agent (1,024 entries). The only trace was a single warning in the &lt;strong&gt;agent's&lt;/strong&gt; own &lt;code&gt;ossec.log&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'agent' message queue is full (1024). Log lines may be lost.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Case 3 lost events in two places on the manager: 73,433 in the manager's logcollector and 24,176 in analysisd. The only traces were warnings in the &lt;strong&gt;manager's&lt;/strong&gt; &lt;code&gt;ossec.log&lt;/code&gt; ("Input queue is full", "Queues are full and no EPS credits, dropping events") and a non-zero &lt;code&gt;events_dropped&lt;/code&gt; in &lt;code&gt;wazuh-analysisd.state&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In all three cases the dashboard looks the same: data thins out and has gaps. Only one of them tells you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check yours
&lt;/h2&gt;

&lt;p&gt;On the agents (this is the case with no alert at all):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"message queue is full"&lt;/span&gt; /var/ossec/logs/ossec.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"Input queue is full|dropping events"&lt;/span&gt; /var/ossec/logs/ossec.log
&lt;span class="nb"&gt;grep &lt;/span&gt;events_dropped /var/ossec/var/run/wazuh-analysisd.state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the alerts index, look for rule &lt;code&gt;203&lt;/code&gt; rather than &lt;code&gt;204&lt;/code&gt;: in our run, &lt;code&gt;203&lt;/code&gt; is what fired.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to take from it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep the agent's client buffer on. It is the only one of the three paths that raises an alert, and it is on by default; turning it off to "stop the warnings" removes the only alarm.&lt;/li&gt;
&lt;li&gt;Do not rely on &lt;code&gt;204&lt;/code&gt; to tell you an agent is flooded. Alert on &lt;code&gt;203&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The other two paths are only visible in &lt;code&gt;ossec.log&lt;/code&gt; and the state file. If nothing reads those, a busy agent or an overloaded manager loses data in silence.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we did not measure
&lt;/h2&gt;

&lt;p&gt;One version (4.14.7), one agent, a file read by logcollector. Not measured: agents receiving syslog over the network, the manager receiving syslog directly (&lt;code&gt;&amp;lt;remote&amp;gt;&lt;/code&gt;), clusters, other kinds of manager overload (CPU, disk), or the real load of 1,600 firewalls. We do not know which of the three cases the original question was.&lt;/p&gt;

&lt;p&gt;Thanks to the Wazuh ambassador whose question on LinkedIn started this.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Free: &lt;a href="https://github.com/xuxu298/rule-doctor-lite" rel="noopener noreferrer"&gt;Rule Doctor Lite&lt;/a&gt;, a read-only script that lists the custom rules that never fired and the likely reason, including rules dropped at load. It only sees event loss when &lt;code&gt;203&lt;/code&gt;/&lt;code&gt;204&lt;/code&gt; fired, which above is case 1.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We sell fixes for two silent-loss cases we can test end to end: custom rules that load but never fire, and alerts the indexer rejects. USD 490 per case, paid only after the fix runs clean on your side. &lt;a href="https://vct.atkvn.com/#fix-pack" rel="noopener noreferrer"&gt;vct.atkvn.com/#fix-pack&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>logging</category>
      <category>security</category>
      <category>linux</category>
    </item>
    <item>
      <title>Wazuh custom rule never fires, and analysisd -t still exits 0: the file name decides</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Sat, 26 Sep 2026 06:21:21 +0000</pubDate>
      <link>https://dev.to/xuxu298/wazuh-custom-rule-never-fires-and-analysisd-t-still-exits-0-the-file-name-decides-58od</link>
      <guid>https://dev.to/xuxu298/wazuh-custom-rule-never-fires-and-analysisd-t-still-exits-0-the-file-name-decides-58od</guid>
      <description>&lt;p&gt;You write a child rule for a stock Wazuh rule, drop it into &lt;code&gt;/var/ossec/etc/rules/&lt;/code&gt;, and run the config check. &lt;code&gt;wazuh-analysisd -t&lt;/code&gt; exits 0. You restart the manager. The rule never fires, and &lt;code&gt;wazuh-logtest&lt;/code&gt; shows the event landing on the parent instead.&lt;/p&gt;

&lt;p&gt;One common cause has nothing to do with the rule itself. It is the name of the file you put it in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we measured
&lt;/h2&gt;

&lt;p&gt;On a throwaway &lt;code&gt;wazuh-manager:4.14.7&lt;/code&gt; container we used one test rule, a child of the stock sshd rule &lt;code&gt;5715&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"test,"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"100080"&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;"9"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;if_sid&amp;gt;&lt;/span&gt;5715&lt;span class="nt"&gt;&amp;lt;/if_sid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;match&amp;gt;&lt;/span&gt;Accepted password&lt;span class="nt"&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;test child of 5715&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;5715&lt;/code&gt; lives in &lt;code&gt;/var/ossec/ruleset/rules/0095-sshd_rules.xml&lt;/code&gt;. We put the same rule in five differently named files in &lt;code&gt;/var/ossec/etc/rules/&lt;/code&gt;, ran &lt;code&gt;wazuh-analysisd -t&lt;/code&gt;, restarted, and sent one line through &lt;code&gt;wazuh-logtest&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Sep 26 10:00:00 host1 sshd[1234]: Accepted password for root from 203.0.113.5 port 22 ssh2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;file&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;-t&lt;/code&gt; exit&lt;/th&gt;
&lt;th&gt;7617 / 7619 warnings&lt;/th&gt;
&lt;th&gt;logtest lands on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0094-test.xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;5715&lt;/code&gt; (our rule ignored)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0096-test.xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;100080&lt;/code&gt; (fires)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;local_rules.xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;100080&lt;/code&gt; (fires)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0095-aaa.xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;5715&lt;/code&gt; (our rule ignored)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0095-zzz.xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;100080&lt;/code&gt; (fires)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two warnings, word for word:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: (7617): Signature ID '5715' was not found and will be ignored in the 'if_sid' option of rule '100080'.
WARNING: (7619): Empty 'if_sid' value. Rule '100080' will be ignored.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What it means
&lt;/h2&gt;

&lt;p&gt;Files in &lt;code&gt;etc/rules&lt;/code&gt; are not loaded after the stock ruleset. They are merged with &lt;code&gt;ruleset/rules&lt;/code&gt; and loaded in order of the &lt;strong&gt;full file name&lt;/strong&gt;. The last two rows show it: &lt;code&gt;0095-aaa.xml&lt;/code&gt; sorts before &lt;code&gt;0095-sshd_rules.xml&lt;/code&gt;, so when our rule is read, &lt;code&gt;5715&lt;/code&gt; does not exist yet and the rule is dropped. &lt;code&gt;0095-zzz.xml&lt;/code&gt; sorts after it, and the same rule fires.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;local_rules.xml&lt;/code&gt; is safe for this reason: letters sort after digits, and all 168 stock rule files in 4.14.7 start with a digit (&lt;code&gt;0010&lt;/code&gt; to &lt;code&gt;0999&lt;/code&gt;), so it loads after every one of them.&lt;/p&gt;

&lt;p&gt;The trap is the config check. &lt;code&gt;wazuh-analysisd -t&lt;/code&gt; exits 0 in all five cases. It prints the two warnings, but a warning is not a failure, and nothing in a deploy script that checks the exit code will stop. The manager then starts cleanly with one rule fewer than you think.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check yours in a minute
&lt;/h2&gt;

&lt;p&gt;After a restart, the warnings are also in the manager log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'\((7617|7619)\)'&lt;/span&gt; /var/ossec/logs/ossec.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every rule id you see in a 7619 line is a rule that is not running. The 7617 line on the same second tells you which parent it was waiting for.&lt;/p&gt;

&lt;p&gt;Before a restart, run the check yourself and read its output instead of trusting the exit code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/var/ossec/bin/wazuh-analysisd &lt;span class="nt"&gt;-t&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'\((7617|7619)\)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a single rule, &lt;code&gt;wazuh-logtest&lt;/code&gt; with a real sample line is the final word: if the output shows the parent's id and not yours, your rule did not load or did not match.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Move the child rule into a file whose name sorts &lt;strong&gt;after&lt;/strong&gt; the file that holds its parent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;put it in &lt;code&gt;local_rules.xml&lt;/code&gt;, or&lt;/li&gt;
&lt;li&gt;give your file a prefix above the parent's file (&lt;code&gt;0096-...&lt;/code&gt; or higher for children of sshd rules), or a name that starts with a letter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To find the parent's file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s1"&gt;'id="5715"'&lt;/span&gt; /var/ossec/ruleset/rules/&lt;span class="k"&gt;*&lt;/span&gt;.xml /var/ossec/etc/rules/&lt;span class="k"&gt;*&lt;/span&gt;.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the check again and confirm the 7619 line is gone, and that logtest lands on your rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we did not measure
&lt;/h2&gt;

&lt;p&gt;One Wazuh version (4.14.7), a single manager, one parent rule, and only &lt;code&gt;if_sid&lt;/code&gt;. We did not test &lt;code&gt;if_matched_sid&lt;/code&gt;, &lt;code&gt;if_group&lt;/code&gt;, decoders, or a cluster. If you run a cluster, check the warnings on every node.&lt;/p&gt;

&lt;p&gt;Credit to Francisco Sousa, who found the file name half of this in his own container before we did.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If one of your rules loads and never fires and you would rather not dig into it yourself, send us the rule, your Wazuh version and a sample event: we find why, then write and test the fix on that version. USD 490 per rule case, paid only after it runs clean on your side. &lt;a href="https://vct.atkvn.com/#fix-pack" rel="noopener noreferrer"&gt;vct.atkvn.com/#fix-pack&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>detectionengineering</category>
      <category>security</category>
      <category>linux</category>
    </item>
    <item>
      <title>Wazuh ms-graph: why Entra ID sign-ins never reach the indexer, and a one-processor fix</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Sat, 26 Sep 2026 02:58:36 +0000</pubDate>
      <link>https://dev.to/xuxu298/wazuh-ms-graph-why-entra-id-sign-ins-never-reach-the-indexer-and-a-one-processor-fix-596k</link>
      <guid>https://dev.to/xuxu298/wazuh-ms-graph-why-entra-id-sign-ins-never-reach-the-indexer-and-a-one-processor-fix-596k</guid>
      <description>&lt;p&gt;You enable the Wazuh &lt;code&gt;ms-graph&lt;/code&gt; module for &lt;code&gt;auditLogs/signIns&lt;/code&gt;. The module logs clean scans. With &lt;code&gt;wazuh_modules.debug=2&lt;/code&gt; it even logs &lt;code&gt;Sending log: {"integration":"ms-graph", ... "relationship":"signIns"}&lt;/code&gt;. And yet there is not a single sign-in in &lt;code&gt;wazuh-alerts-*&lt;/code&gt; or &lt;code&gt;wazuh-archives-*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are two separate reasons, and on a stock install you hit both.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The stock ruleset has no rule for sign-ins
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;0995-microsoft-graph_rules.xml&lt;/code&gt; in 4.14.7 has 99 rules. The parent rule &lt;code&gt;99500&lt;/code&gt; (level 0) catches every ms-graph event. Its children cover alerts, incidents, audit events, devices, apps and risk detections. None matches &lt;code&gt;relationship: signIns&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So on the stock ruleset a sign-in stops at level 0 and never becomes an alert. It can only reach the indexer through the archives (&lt;code&gt;&amp;lt;logall_json&amp;gt;yes&amp;lt;/logall_json&amp;gt;&lt;/code&gt;). That is where the second problem waits.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The stock template rejects every sign-in
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;wazuh-template.json&lt;/code&gt; applies to both &lt;code&gt;wazuh-alerts-4.x-*&lt;/code&gt; and &lt;code&gt;wazuh-archives-4.x-*&lt;/code&gt;. It maps two ms-graph fields as &lt;code&gt;keyword&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;field&lt;/th&gt;
&lt;th&gt;template&lt;/th&gt;
&lt;th&gt;alerts_v2 / incidents send&lt;/th&gt;
&lt;th&gt;signIns send&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data.ms-graph.status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;keyword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a string (&lt;code&gt;"resolved"&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;an object (&lt;code&gt;{errorCode, failureReason, additionalDetails}&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data.ms-graph.appliedConditionalAccessPolicies&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;keyword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;not sent&lt;/td&gt;
&lt;td&gt;a list of objects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;keyword&lt;/code&gt; field cannot hold an object, so the indexer rejects the document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mapper_parsing_exception: failed to parse field [data.ms-graph.status] of type [keyword] ...
caused_by: illegal_state_exception: Can't get text on a START_OBJECT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three details that make this harder to see than it should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It does not depend on which event arrives first.&lt;/strong&gt; "First shape wins" only holds for unmapped fields. These two are mapped explicitly, so every object-shaped sign-in is rejected, in any order, even if &lt;code&gt;signIns&lt;/code&gt; is the only relationship you enabled. We checked the template at tags &lt;code&gt;v4.8.0&lt;/code&gt;, &lt;code&gt;v4.10.0&lt;/code&gt;, &lt;code&gt;v4.12.0&lt;/code&gt;, &lt;code&gt;v4.14.0&lt;/code&gt;, &lt;code&gt;v4.14.3&lt;/code&gt; and &lt;code&gt;v4.14.7&lt;/code&gt;: the same in all six.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The error names only the first bad field.&lt;/strong&gt; A sign-in with at least one Conditional Access policy fails on &lt;code&gt;appliedConditionalAccessPolicies&lt;/code&gt;. One with an empty policy list fails on &lt;code&gt;status&lt;/code&gt;. Fix &lt;code&gt;status&lt;/code&gt; alone and the sign-ins that had a policy applied are still rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing on the manager says so.&lt;/strong&gt; &lt;code&gt;ossec.log&lt;/code&gt; is clean and &lt;code&gt;archives.json&lt;/code&gt; has the event. The rejection happens inside the indexer, after Filebeat has shipped the event. One of the reporters found nothing in the Filebeat log either.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the sign-in is missing from &lt;code&gt;archives.json&lt;/code&gt; itself, you have a different problem, upstream of the indexer. Look at &lt;code&gt;time_delay&lt;/code&gt; first: sign-in records show up in Graph with a delay, and a scan window that closes at "now" can miss them. Issue 39460 in wazuh/wazuh has both problems, one after the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check yours in a minute
&lt;/h2&gt;

&lt;p&gt;On the stock template timing does not matter, so the mapping tells you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;GET wazuh-archives-*,wazuh-alerts-*/_mapping/field/data.ms-graph.status,data.ms-graph.appliedConditionalAccessPolicies
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If either field comes back &lt;code&gt;"type": "keyword"&lt;/code&gt; and you have &lt;code&gt;signIns&lt;/code&gt; enabled, every sign-in that reaches the indexer is rejected: through the archives, or through the alerts index once you add your own sign-in rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: one &lt;code&gt;script&lt;/code&gt; processor, by type
&lt;/h2&gt;

&lt;p&gt;The idea is to leave the string &lt;code&gt;status&lt;/code&gt; of alerts and incidents where it is, because dashboards and saved searches on &lt;code&gt;data.ms-graph.status&lt;/code&gt; expect that string. Only the sign-in shapes move to new fields. The rules are not affected either way: they run on the manager, before the indexer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt;, when it is an object → &lt;code&gt;data.ms-graph.signInStatus&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appliedConditionalAccessPolicies&lt;/code&gt;, when it is a list of objects → &lt;code&gt;data.ms-graph.conditionalAccessPolicies&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is one &lt;code&gt;script&lt;/code&gt; processor (&lt;code&gt;FIX&lt;/code&gt; in the script at the end), right after the &lt;code&gt;json&lt;/code&gt; processor, in the &lt;strong&gt;alerts and the archives&lt;/strong&gt; pipeline. Two details matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ignore_failure: true&lt;/code&gt;. The stock Wazuh pipelines end with &lt;code&gt;on_failure: drop&lt;/code&gt;, so a processor that throws does not just skip its own step; the whole event is dropped. With &lt;code&gt;ignore_failure&lt;/code&gt;, the worst case is an event indexed unchanged.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;d.get('ms-graph')&lt;/code&gt;, not &lt;code&gt;ctx.data?.ms-graph&lt;/code&gt;. Painless reads the hyphen as a minus sign, the dotted form does not compile, and the indexer refuses the whole pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The two new fields get a dynamic mapping on first use (&lt;code&gt;signInStatus.errorCode&lt;/code&gt; becomes &lt;code&gt;long&lt;/code&gt;, the text fields &lt;code&gt;keyword&lt;/code&gt;). No template change is needed, and the fix works on today's index too; you do not wait for the next daily index.&lt;/p&gt;

&lt;p&gt;The script at the end of this post does this for you, with a backup and a rollback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://&amp;lt;indexer&amp;gt;:9200 &lt;span class="nv"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;'&lt;/span&gt;
python3 msgraph_signins_fix.py verify     &lt;span class="c"&gt;# 4 test events through your live pipelines&lt;/span&gt;
python3 msgraph_signins_fix.py apply      &lt;span class="c"&gt;# saves both pipelines to ./backup, installs the processor&lt;/span&gt;
python3 msgraph_signins_fix.py verify     &lt;span class="c"&gt;# expect 0 problems&lt;/span&gt;
python3 msgraph_signins_fix.py rollback   &lt;span class="c"&gt;# restores ./backup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What we measured, and what we did not
&lt;/h2&gt;

&lt;p&gt;Measured on a throwaway &lt;code&gt;wazuh-indexer:4.14.7&lt;/code&gt; with the stock template and both stock pipelines, taken from the &lt;code&gt;wazuh-manager:4.14.7&lt;/code&gt; image. We sent Graph v1.0-shaped sign-ins, with and without a Conditional Access policy, plus an &lt;code&gt;alerts_v2&lt;/code&gt; alert, the way Filebeat sends them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stock: every sign-in rejected, in both pipelines and in both arrival orders; the alert indexes fine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; fixed alone: sign-ins that had a policy applied still rejected, now on the second field&lt;/li&gt;
&lt;li&gt;the processor: every sign-in and the alert indexed, in both orders, in a fresh index and in an index that already existed; &lt;code&gt;data.ms-graph.status&lt;/code&gt; stays &lt;code&gt;keyword&lt;/code&gt; and still aggregates; events without &lt;code&gt;data&lt;/code&gt; are untouched&lt;/li&gt;
&lt;li&gt;the script: &lt;code&gt;verify&lt;/code&gt; 4 errors → &lt;code&gt;apply&lt;/code&gt; → &lt;code&gt;verify&lt;/code&gt; 0 of 8 (including a non-ms-graph event) → a second &lt;code&gt;apply&lt;/code&gt; skips → &lt;code&gt;rollback&lt;/code&gt; restores both pipelines byte for byte → &lt;code&gt;verify&lt;/code&gt; 4 errors again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not measured: a real tenant, the Graph beta API (it adds sign-in fields we have not checked against the template), a real Filebeat in the path, and whether the patch survives a restart or upgrade. Two things to check on your side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your &lt;code&gt;filebeat.yml&lt;/code&gt; sets &lt;code&gt;filebeat.overwrite_pipelines: true&lt;/code&gt;, Filebeat reloads the pipeline from disk and the patch has to go into the pipeline file instead.&lt;/li&gt;
&lt;li&gt;After a Wazuh upgrade, the pipeline id can change. Run &lt;code&gt;verify&lt;/code&gt; again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And to get sign-in &lt;strong&gt;alerts&lt;/strong&gt; rather than archives only, you still need your own rule on &lt;code&gt;ms-graph.relationship&lt;/code&gt; = &lt;code&gt;signIns&lt;/code&gt;. The stock ruleset does not ship one.&lt;/p&gt;

&lt;p&gt;Credit to the reporters of wazuh/wazuh issues 38330 and 39460: the first described the collision, the second narrowed the loss down to the indexer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The script
&lt;/h2&gt;

&lt;p&gt;Save it as &lt;code&gt;msgraph_signins_fix.py&lt;/code&gt;. Standard library only; it changes nothing but the two pipelines, and &lt;code&gt;verify&lt;/code&gt; writes only to indices dated &lt;code&gt;2099.01.01&lt;/code&gt;, then deletes them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
# Wazuh ms-graph sign-in fix: verify | apply | rollback. ATK New Technology, vct.atkvn.com/#fix-pack
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;rstrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AUTH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;TAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ms-graph signIns fix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;def d = ctx.get(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;); if (!(d instanceof Map)) { return; } &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;def g = d.get(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ms-graph&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;); if (!(g instanceof Map)) { return; } &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;if (g.get(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;) instanceof Map) { g.put(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;signInStatus&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, g.remove(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)); } &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;def p = g.get(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;appliedConditionalAccessPolicies&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;); &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;if (p instanceof List &amp;amp;&amp;amp; !p.isEmpty() &amp;amp;&amp;amp; p.get(0) instanceof Map) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{ g.put(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;conditionalAccessPolicies&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, g.remove(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;appliedConditionalAccessPolicies&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)); }&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;FIX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lang&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;painless&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SRC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore_failure&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TAG&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;es&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                                 &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Basic &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# stock Wazuh indexers use self-signed certificates
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_create_unverified_context&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pipelines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;es&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_ingest/pipeline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cannot list pipelines: HTTP %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alerts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;archives&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;allp&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filebeat-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-wazuh-%s-pipeline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no filebeat-*-wazuh-%s-pipeline found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;allp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;pipelines&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;procs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;processors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TAG&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;script&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;procs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;already patched&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;procs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%s has no json processor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;es&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_ingest/pipeline/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;processors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;procs&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;FIX&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;procs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HTTP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;pipelines&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;restored, HTTP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;es&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/_ingest/pipeline/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)))[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no backup, left as is&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;  &lt;span class="c1"&gt;# writes only to indices dated 2099.01.01, then deletes them
&lt;/span&gt;    &lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;integration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ms-graph&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ms-graph&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errorCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50126&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;failureReason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid username or password.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;pol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;displayName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notApplied&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="n"&gt;cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;other event&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;srcip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;203.0.113.7&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alerts_v2, string status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;relationship&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alerts_v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signIns + policies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;appliedConditionalAccessPolicies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;relationship&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signIns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signIns, no policies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;appliedConditionalAccessPolicies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;relationship&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signIns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="n"&gt;bad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;pipelines&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wazuh-%s-4.x-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cases&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2099-01-01T00:00:00.000+0000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rule&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;99500&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;es&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/%sverify/_doc?pipeline=%s&amp;amp;refresh=true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                         &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fields&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index_prefix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;
            &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2099.01.01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;bad&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%-8s %-26s %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ERROR %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="nf"&gt;es&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DELETE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/%s2099.01.01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bad&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;problem(s)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bad&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apply&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rollback&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage: URL=https://&amp;lt;indexer&amp;gt;:9200 AUTH=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; %s verify|apply|rollback&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;If you would rather not patch this yourself, we write and test the fix for your exact Wazuh version and send you the files: USD 490, paid only after it runs clean on your side. &lt;a href="https://vct.atkvn.com/#fix-pack" rel="noopener noreferrer"&gt;vct.atkvn.com/#fix-pack&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dong Nguyen, ATK New Technology&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>microsoft365</category>
      <category>opensearch</category>
    </item>
    <item>
      <title>One field path, two shapes: how Wazuh alerts get dropped with a 400 nobody sees</title>
      <dc:creator>Nguyen Dong</dc:creator>
      <pubDate>Thu, 24 Sep 2026 11:12:36 +0000</pubDate>
      <link>https://dev.to/xuxu298/one-field-path-two-shapes-how-wazuh-alerts-get-dropped-with-a-400-nobody-sees-1flf</link>
      <guid>https://dev.to/xuxu298/one-field-path-two-shapes-how-wazuh-alerts-get-dropped-with-a-400-nobody-sees-1flf</guid>
      <description>&lt;p&gt;In the last 24 hours, two people running Wazuh 4.14.7 in production hit the same defect from different directions, and neither of them saw it on a dashboard. They found it by going looking in a log.&lt;/p&gt;

&lt;p&gt;The defect is simple to state. The alerts index template gives each field path one type. Some integrations send more than one shape of data under the same path. When an event arrives in the shape the template did not expect, the indexer rejects that document with &lt;code&gt;mapper_parsing_exception&lt;/code&gt;, Filebeat gets a 400 back, and a 400 is not the kind of error a shipper retries. The event is gone. Nothing alerts on it, because the thing that would alert is the thing that never got stored.&lt;/p&gt;

&lt;p&gt;Three paths so far. &lt;code&gt;data.ms-graph.status&lt;/code&gt; is mapped as &lt;code&gt;keyword&lt;/code&gt;, and some Microsoft Graph events send an object there. &lt;code&gt;data.office365.ModifiedProperties&lt;/code&gt; is also &lt;code&gt;keyword&lt;/code&gt;, and some Office 365 events send an object; one operator counted 35 of those in a single Filebeat log. The third runs the other way: an override that mapped &lt;code&gt;data.data&lt;/code&gt; as an object then met events that send the string &lt;code&gt;"[]"&lt;/code&gt; in the same place.&lt;/p&gt;

&lt;p&gt;The useful part is that this is one class of bug, not three. Any path that can carry two shapes will drop the minority shape silently, so the audit is a count of failures by field name, not a hunt for a specific field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'failed to parse field \[[^]]*\]'&lt;/span&gt; /var/log/filebeat/filebeat&lt;span class="k"&gt;*&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An empty result is only meaningful if Filebeat logs at a level that records the rejection, so check that one known-bad event shows up before trusting a zero.&lt;/p&gt;

&lt;p&gt;On the fix, put the override in a template of its own with a higher &lt;code&gt;order&lt;/code&gt; instead of editing the &lt;code&gt;wazuh&lt;/code&gt; template, which the documented upgrade procedure reinstalls. On 4.14.7 two legacy templates with the same pattern merge and the higher &lt;code&gt;order&lt;/code&gt; wins the field; that part I measured. Remember a template only applies when an index is created, so today's index keeps the old mapping and keeps dropping until tomorrow's index exists. And before you flip a path from &lt;code&gt;keyword&lt;/code&gt; to &lt;code&gt;object&lt;/code&gt;, run an &lt;code&gt;exists&lt;/code&gt; query on it: every hit is an event that indexed fine as a string, and flipping the type moves the 400s onto those. If both shapes are real, &lt;code&gt;enabled: false&lt;/code&gt; accepts both (one of the two operators measured this on &lt;code&gt;status&lt;/code&gt;), at the price of not being able to query inside that field.&lt;/p&gt;

&lt;p&gt;If you run the grep and get a path that is not on this list, I'd like to hear which one.&lt;/p&gt;

</description>
      <category>wazuh</category>
      <category>security</category>
      <category>opensearch</category>
    </item>
  </channel>
</rss>
