Wazuh Tuning Guide: Reducing False Positives Without Losing Detection Coverage
Wazuh out of the box generates alerts from level 3 upward, which in any active environment means hundreds to thousands of alerts per day before any tuning. Most of them are informational: successful SSH logins, sudo usage, agent restarts, cron job execution. Tuning Wazuh is a three-step process -- understand the rule pipeline, suppress known-good activity with child rules, and apply different profiles to different asset classes using agent groups.
Understanding the Wazuh Rule Pipeline
Log collection path: agent collects log, sends to manager, decoder parses fields, rules evaluate fields, alert generated if threshold met.
Decoder locations:
- Built-in decoders: /var/ossec/ruleset/decoders/
- Custom decoders: /var/ossec/etc/decoders/local_decoder.xml
Rule locations:
- Built-in rules: /var/ossec/ruleset/rules/
- Custom rules: /var/ossec/etc/rules/local_rules.xml
Rule hierarchy: parent rule fires first, child rules inherit parent match and add conditions. Wazuh evaluates child rules sequentially.
Alert levels: 1-7 (low), 8-11 (medium), 12-14 (high), 15 (maximum). Default forward threshold: level 3.
Testing a log line:
echo "May 20 10:00:00 server sshd[1234]: Accepted publickey for deploy from 10.0.1.5" | /var/ossec/bin/wazuh-logtest
Identifying Your Noisiest Rules
Query the Wazuh archives directly for top-firing rules:
grep "rule id" /var/ossec/logs/archives/archives.log \
| awk '{print $NF}' \
| sort | uniq -c | sort -rn | head -20
For Wazuh API queries:
curl -k -X GET "https://localhost:55000/alerts?limit=1&select=rule.id,rule.description&sort=-rule.id" \
-H "Authorization: Bearer $(curl -k -u admin:admin \
https://localhost:55000/security/user/authenticate | jq -r '.data.token')"
Wazuh dashboard approach: use the Discover view, aggregate by the rule.id field, and sort by count descending.
Top 5 noise sources in most deployments:
- Rule 5715: sshd authentication success
- Rule 5104: new dpkg package installed
- Rule 2501: user login success
- Rule 591: integrity check
- Rule 1002: unknown problem in a monitored application
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Writing Suppression Rules in local_rules.xml
Rule to suppress SSH success alerts from known IPs:
<!-- Suppress SSH success from monitoring system -->
<rule id="100001" level="0">
<if_sid>5715</if_sid>
<srcip>10.0.0.50</srcip>
<description>Ignore: SSH success from monitoring system</description>
</rule>
Rule to reduce an alert to informational rather than suppress entirely:
<!-- Reduce sudo alerts from deploy user to informational -->
<rule id="100002" level="3" overwrite="yes">
<if_sid>5402</if_sid>
<user>deploy</user>
<description>Sudo usage by deploy user (expected)</description>
</rule>
Level 0 rules suppress the alert entirely. Use with care -- document why in the description so future engineers understand the intent.
Reload rules without a full restart:
kill -HUP $(cat /var/ossec/var/run/wazuh-analysisd.pid)
Custom Decoders for Application Logs
When Wazuh does not parse your application logs, create a custom decoder in /var/ossec/etc/decoders/local_decoder.xml.
Example: parsing a custom application log format:
<decoder name="myapp">
<prematch>^MyApp\[</prematch>
</decoder>
<decoder name="myapp_fields">
<parent>myapp</parent>
<regex>MyApp\[(\d+)\] (\w+): (.+)</regex>
<order>pid, level, message</order>
</decoder>
Test the decoder with wazuh-logtest:
echo "MyApp[1234] ERROR: payment gateway timeout" | /var/ossec/bin/wazuh-logtest
The tool shows which decoder fired, what fields were extracted (pid=1234, level=ERROR, message=payment gateway timeout), and which rules matched. Once the decoder is working, write rules that evaluate the decoded level and message fields to generate alerts only on actionable events.
Agent Groups for Environment-Specific Tuning
Create a group via the Wazuh API:
curl -k -X POST "https://localhost:55000/groups" \
-H "Authorization: Bearer [token]" \
-d '{"group_id": "production-web"}'
Add an agent.conf to the group directory at /var/ossec/etc/shared/production-web/agent.conf. Example override for web servers that suppresses noisy Apache access log chatter:
<agent_config>
<localfile>
<location>/var/log/apache2/access.log</location>
<log_format>apache</log_format>
</localfile>
<ossec_config>
<alerts>
<email_alert_level>12</email_alert_level>
</alerts>
</ossec_config>
</agent_config>
Assign an agent to the group:
curl -k -X PUT \
"https://localhost:55000/agents/[agent-id]/group/production-web" \
-H "Authorization: Bearer [token]"
Database servers, web servers, and workstations can each have their own agent group with different suppression rules and alert thresholds.
Testing Changes and Validating Coverage
After any rule change, verify that actual threat patterns still trigger alerts. Run wazuh-logtest with log lines that represent real attacks:
SSH brute force validation:
for i in {1..6}; do
echo "May 20 10:00:0$i server sshd[1234]: Failed password for root from 1.2.3.4 port 22 ssh2" \
| /var/ossec/bin/wazuh-logtest
done
Rootcheck validation: confirm rule 510 (rootcheck) still fires after tuning changes that touch integrity rules.
Coverage regression checklist:
- Maintain a file of "should alert" log samples organized by rule category
- Run wazuh-logtest against all samples before and after any tuning change
- Compare rule IDs that fired -- any missing rule IDs from the post-change run are regressions
Monitor alert volume trends in the Wazuh dashboard. A sudden 80% drop in a specific rule category is not noise reduction -- it is a signal that a suppression rule went too wide.
The bottom line
Wazuh tuning is not about silencing alerts -- it is about routing signal to the right level. Use child rules to suppress known-good activity at level 0, reduce noisy-but-relevant rules to level 3-5, and apply different profiles to different asset classes with agent groups. Always test that actual threat patterns still trigger alerts after tuning changes. A well-tuned Wazuh deployment generates 50-200 actionable alerts per day, not 5,000.
Frequently asked questions
Where do I add custom rules in Wazuh without them being overwritten on upgrade?
All custom rules go in /var/ossec/etc/rules/local_rules.xml. Wazuh preserves this file during upgrades. Never modify files under /var/ossec/ruleset/rules/ -- those are owned by the Wazuh package and will be replaced.
How do I suppress a specific Wazuh alert without disabling the rule?
Use a rule with <match> and <if_sid> that references the original rule and sets <options>no_log</options>, or use <ignore> in ossec.conf for specific decoders. The cleanest approach: write a child rule with <if_sid>[original-rule-id]</if_sid> that matches the false-positive pattern and overwrite="yes" with a lower level.
What is the difference between a decoder and a rule in Wazuh?
A decoder extracts structured fields from raw log text (parsing). A rule evaluates the decoded fields and determines the alert level and category. You tune decoders when logs aren't being parsed correctly; you tune rules when alerts fire on events that aren't threats.
How do I create different Wazuh tuning profiles for different servers?
Use agent groups. Create groups in the Wazuh manager (/var/ossec/etc/shared/[group-name]/), add an agent.conf per group with group-specific rule exceptions or configurations, and assign agents to groups. Database servers, web servers, and workstations can have different alert thresholds.
How do I test a custom Wazuh rule before deploying it?
Use /var/ossec/bin/wazuh-logtest (previously ossec-logtest). Enter a raw log line and it shows you which decoder fired, what fields were extracted, and which rules matched. Essential before deploying any custom rule change.
What level should I set for my Wazuh alerts to avoid flooding?
Default alert threshold in ossec.conf is level 3. For SIEM forwarding, consider raising to level 7 (significant) or level 10 (critical). Use level filtering in your log forwarding config, not by disabling rules -- this preserves local Wazuh visibility while reducing SIEM noise.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, weekly, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals weekly.
The Mythos Brief is free.
AI that finds 27-year-old zero-days. What it means for your security program.
