August 5, 2026 by Victor M. Alvarez3 minutes
When crafting YARA rules, wildcard pattern sets like any of ($s*) or
all of ($c*) are a very convenient feature of the language. They allow
rule authors to group related strings under a common prefix, keeping
condition logic clean and maintainable.
However, while inspecting real-world YARA rules in search of optimization opportunities, I realized that wildcard pattern sets are also one of the subtlest sources of silent logic bugs. Consider this YARA rule:
rule example_1 {
strings:
$b1 = "pluginWrapper plugin_"
$b2 = "data-areaid="
$b3 = "PowerbyDedeCms"
$b4 = "dede_fieldshash"
$b5 = "/plus/diy.php"
$bd1 = "@eval($_POST["
$bd2 = "@Assert($_POST["
condition:
2 of ($b*) and 1 of ($bd*)
} The intention of this rule seems clear: it should detect any file
containing two occurrences of the patterns $b1 through $b5, and one
occurrence of either $bd1 or $bd2. Right?
Well, that may be the intention, but it’s not what the rule actually does. Do you see why? Take another look.
The issue here is that $b* matches every pattern identifier starting
with $b—which includes $b1 through $b5, but also $bd1 and $bd2.
In practice, because of the 1 of ($bd*) clause, the condition requires either
$bd1 or $bd2 to be present. If both $bd1 and $bd2 are present, they
themselves satisfy 2 of ($b*), meaning none of the strings $b1 through $b5
are required at all! If only one of $bd1 or $bd2 is present, then only a
single occurrence from $b1 through $b5 is required—not two, as 2 of ($b*)
seems to suggest. The matching occurrence of $bd1 or $bd2 counts toward
evaluating 2 of ($b*).
Perhaps the rule’s author intended this exact behavior, but I doubt it. Now take a look at another example where the error is even more obvious:
rule example_2 {
strings:
$this = "This program cannot be run"
$t1 = "SAServer"
$t2 = "Pass:"
$t3 = "User:"
condition:
$this and 1 of ($t*)
}The $this pattern is explicitly required, but because $t* also matches $this,
the 1 of ($t*) clause is completely redundant. If $this is true, then 1 of ($t*)
is automatically true as well, regardless of whether $t1, $t2, or $t3 are found.
Issues like these turn out to be quite common in real-world rules, and I’ve found multiple examples among the rules we have in VirusTotal. So I decided to implement a new compiler warning to help detect this kind of error automatically. It proved more challenging than I initially expected, but after a few iterations, I arrived at a solution that works remarkably well.
Here is what the warning looks like in action:
warning[unintended_pattern_in_set]: pattern `$this` may be unintendedly or redundantly included in pattern set `$t*`
--> test.yar:9:5
|
9 | $this and 1 of ($t*)
| ----- --- `$this` is also included in `$t*`
| |
| `$this` is used hereThis feature will be released in the upcoming YARA-X v1.20.0. Until then, let me know what you think about it!