Testing YARA rules: samples, goodware and CI
How to test YARA rules before deploying them: positive samples, a goodware corpus for false positives, yr check, unit tests and a GitHub Actions CI pipeline.
A rule that has never been tested is a guess. Testing answers three questions: does it compile, does it match what it should, and does it stay silent on everything else? This guide sets up a simple routine you can run by hand and in CI.
Why test
- Syntax drift. A rule written for YARA 4 may fail to compile with YARA-X, or the other way round.
- Missed detections. A typo in a hex string or an overly strict condition makes a rule silently useless.
- False positives. Generic strings match installers, browsers and system DLLs. In production that means alert fatigue and lost trust.
- Performance regressions. One slow pattern degrades every scan (see performance).
Build a small test corpus
Keep two directories next to your rules:
tests/positive/— samples the rule must match. For malware, store them encrypted (for example in a password-protected archive) or reference them by hash and fetch them in a controlled environment.tests/goodware/— clean files the rule must not match: system binaries from several OS versions, common installers, office documents, scripts. Larger is better; public goodware collections exist, and your own golden images are ideal.
For logic that doesn't require real malware, craft tiny synthetic files. A file that contains only your marker strings in the right place is enough to test a condition.
# A synthetic positive: MZ header + the two strings the rule expects
printf 'MZ' > tests/positive/synthetic.bin
head -c 200 /dev/zero >> tests/positive/synthetic.bin
printf 'LoaderInit\0GetProcAddress\0' >> tests/positive/synthetic.bin
Compile and format checks
The YARA-X command-line tool yr has the checks you need:
yr check rules/ # compile everything, report errors and warnings
yr fmt rules/example.yar # rewrite a file in the canonical format
yr scan rules/example.yar tests/positive/ # must print every positive sample
yr scan rules/example.yar tests/goodware/ # must print nothing
With YARA 4.x, yarac compiles and yara -r scans recursively.
A test rule to start from
rule MAL_Test_Target
{
meta:
= "Target rule used in the testing guide"
= "yararules.org"
= "2026-09-29"
strings:
$a = "LoaderInit" ascii
$b = "GetProcAddress" ascii
condition:
uint16(0) == 0x5A4D and filesize < 1MB and all of them
}
The synthetic file above matches it; any clean executable that lacks LoaderInit does not. Try both in the online editor: paste the rule, drop the file on the test pane, and see the matched strings with their offsets.
Continuous integration
Run the same checks on every change. A minimal GitHub Actions workflow:
name: yara
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install YARA-X
run: cargo install yara-x-cli
- name: Compile
run: yr check rules/
- name: Positive samples must match
run: |
for f in tests/positive/*; do
yr scan rules/ "$f" | grep -q . || { echo "no match: $f"; exit 1; }
done
- name: Goodware must not match
run: |
out=$(yr scan rules/ tests/goodware/ || true)
if [ -n "$out" ]; then echo "$out"; exit 1; fi
Installing from crates.io builds YARA-X from source; you can also download a prebuilt release binary from the YARA-X releases page to speed the job up.
Track false positives over time
- Record every false positive with the file hash, the rule and the fix, then add the file to the goodware corpus so it never regresses.
- Prefer adding a
$fp*exclusion or a tighter structural check over deleting a useful string. - Consider a
scoremeta field (0–100) so that consumers can weigh weak rules differently from high-confidence ones.
Version your rules
Keep metadata that makes rules maintainable: a stable id (a UUID), date of creation, modified date, author, reference, and sample hash values. The style guide lists common conventions. When a rule changes behaviour, update modified so downstream users know to re-test.
Quick checklist
yr checkpasses with no errors (and warnings reviewed).- Every positive sample matches.
- The goodware corpus produces zero matches.
- The linter shows no performance warnings, or each one is justified.
- Metadata is complete and
modifiedis current.
FAQ
- How can I test a YARA rule online?
- Paste the rule into the editor on this site and drop a sample file on the test pane. YARA-X runs in your browser as WebAssembly, so the file is never uploaded.
- What is a goodware corpus?
- A collection of known-clean files, such as operating-system binaries and common software installers, used to measure how often a rule matches legitimate files.
- Which command checks the syntax of YARA-X rules?
- yr check rules.yar compiles the rules and reports errors and warnings without scanning anything.