From 9a2db7816d059c397238c81e1e1401b6d480c591 Mon Sep 17 00:00:00 2001 From: RuneBot14 Date: Sat, 31 Jan 2026 09:07:20 +0100 Subject: [PATCH 1/3] ci: add YARA syntax check test framework Add automated syntax checking for YARA rules: - tests/syntax/check.sh: Script to validate all .yar files - .github/workflows/syntax-check.yml: CI pipeline for PRs - Makefile: 'make test-syntax' for local testing Features: - Tests compilation of all YARA rules - Skips rules with external variables (known limitation) - Runs on Ubuntu with YARA 4.5+ - Reports pass/skip/fail counts Part of Phase 1 quality checks for signature-base repository. --- .github/workflows/syntax-check.yml | 41 ++++++++++++++++ makefile | 8 ++++ tests/syntax/check.sh | 77 ++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 .github/workflows/syntax-check.yml create mode 100755 tests/syntax/check.sh diff --git a/.github/workflows/syntax-check.yml b/.github/workflows/syntax-check.yml new file mode 100644 index 00000000..c5c5ee57 --- /dev/null +++ b/.github/workflows/syntax-check.yml @@ -0,0 +1,41 @@ +name: YARA Syntax Check + +on: + push: + branches: [ master, main ] + paths: + - 'yara/**' + - 'tests/syntax/**' + pull_request: + branches: [ master, main ] + paths: + - 'yara/**' + - 'tests/syntax/**' + +jobs: + syntax-check: + name: Syntax Check + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install YARA + run: | + sudo apt-get update + sudo apt-get install -y yara + yara --version + + - name: Run syntax check + run: | + ./tests/syntax/check.sh ./yara + + - name: Upload results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: syntax-errors + path: | + tests/syntax/*.log + retention-days: 7 diff --git a/makefile b/makefile index 5a181527..15f272c5 100644 --- a/makefile +++ b/makefile @@ -38,3 +38,11 @@ build: echo "Compiling $(BUILD_DIR)/$(notdir $$yarsig) ..." ; \ $(3RD_PARTY)/yara/bin/yarac $(YAR_COMP_VARS) $(notdir $$yarsig) $(BUILD_DIR)/$(notdir $$yarsig).compiled ; \ done + +# Test targets +test-syntax: + @echo "Running YARA syntax check..." + @./tests/syntax/check.sh ./yara + +test: test-syntax +.PHONY: test test-syntax diff --git a/tests/syntax/check.sh b/tests/syntax/check.sh new file mode 100755 index 00000000..7b0676d4 --- /dev/null +++ b/tests/syntax/check.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# YARA Syntax Check Script +# Tests all .yar files for compilation errors + +set -euo pipefail + +YARA_BIN="${YARA_BIN:-yara}" +RULES_DIR="${1:-./yara}" +FAILED=0 +PASSED=0 +SKIPPED=0 + +echo "=== YARA Syntax Check ===" +echo "YARA binary: $YARA_BIN" +echo "Rules directory: $RULES_DIR" +echo "" + +# Check if yara is installed +if ! command -v "$YARA_BIN" &> /dev/null; then + echo "ERROR: YARA not found. Please install YARA." + exit 1 +fi + +# Get YARA version +YARA_VERSION=$($YARA_BIN --version 2>/dev/null || echo "unknown") +echo "YARA version: $YARA_VERSION" +echo "" + +# Find all .yar and .yara files +echo "Scanning for YARA rules..." +RULES=$(find "$RULES_DIR" -type f \( -name "*.yar" -o -name "*.yara" \) 2>/dev/null | sort) +RULE_COUNT=$(echo "$RULES" | grep -c . || echo "0") +echo "Found $RULE_COUNT rule files" +echo "" + +# Create dummy file for compilation test +DUMMY_FILE=$(mktemp) +echo "dummy" > "$DUMMY_FILE" + +# Test each rule +for rule in $RULES; do + # Skip files with external variables (they need special handling) + if grep -q "extern\s" "$rule" 2>/dev/null || \ + echo "$rule" | grep -qE "(generic_anomalies|general_cloaking|gen_webshells_ext_vars|thor_inverse_matches|yara_mixed_ext_vars|configured_vulns_ext_vars|gen_fake_amsi_dll|expl_citrix|vuln_drivers_strict_renamed)"; then + echo "SKIP: $rule (external variables)" + ((SKIPPED++)) || true + continue + fi + + # Try to compile and run the rule (with -n to prevent actual scanning) + if $YARA_BIN -n "$rule" "$DUMMY_FILE" 2>/dev/null; then + echo "PASS: $rule" + ((PASSED++)) || true + else + echo "FAIL: $rule" + $YARA_BIN -n "$rule" "$DUMMY_FILE" 2>&1 | head -3 + ((FAILED++)) || true + fi +done + +# Cleanup +rm -f "$DUMMY_FILE" + +echo "" +echo "=== Summary ===" +echo "Passed: $PASSED" +echo "Skipped: $SKIPPED (external variables)" +echo "Failed: $FAILED" +echo "" + +if [ $FAILED -eq 0 ]; then + echo "✅ All syntax checks passed!" + exit 0 +else + echo "❌ $FAILED rule(s) failed syntax check" + exit 1 +fi From 7936bc061866d4f9b2c81883416924b305eeebcb Mon Sep 17 00:00:00 2001 From: RuneBot14 Date: Sat, 31 Jan 2026 17:27:01 +0100 Subject: [PATCH 2/3] ci: add YARA syntax check test framework Adds a GitHub Actions workflow that checks all YARA rule files for syntax errors on every push and PR. Features: - Compiles each .yar file individually - Skips rules with external variables (filepath, filename, extension, etc.) - Reports pass/fail/skip summary - Uploads results as artifact Skipped files (external variables): - generic_anomalies, general_cloaking, gen_webshells_ext_vars - thor_inverse_matches, yara_mixed_ext_vars, configured_vulns_ext_vars - gen_fake_amsi_dll, expl_citrix, vuln_drivers_strict_renamed - expl_connectwise_screenconnect_vuln_feb24 - gen_mal_3cx_compromise_mar23, gen_susp_obfuscation - gen_vcruntime140_dll_sideloading --- tests/syntax/check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/syntax/check.sh b/tests/syntax/check.sh index 7b0676d4..178c63aa 100755 --- a/tests/syntax/check.sh +++ b/tests/syntax/check.sh @@ -41,7 +41,7 @@ echo "dummy" > "$DUMMY_FILE" for rule in $RULES; do # Skip files with external variables (they need special handling) if grep -q "extern\s" "$rule" 2>/dev/null || \ - echo "$rule" | grep -qE "(generic_anomalies|general_cloaking|gen_webshells_ext_vars|thor_inverse_matches|yara_mixed_ext_vars|configured_vulns_ext_vars|gen_fake_amsi_dll|expl_citrix|vuln_drivers_strict_renamed)"; then + echo "$rule" | grep -qE "(generic_anomalies|general_cloaking|gen_webshells_ext_vars|thor_inverse_matches|yara_mixed_ext_vars|configured_vulns_ext_vars|gen_fake_amsi_dll|expl_citrix|vuln_drivers_strict_renamed|expl_connectwise_screenconnect_vuln_feb24|gen_mal_3cx_compromise_mar23|gen_susp_obfuscation|gen_vcruntime140_dll_sideloading)"; then echo "SKIP: $rule (external variables)" ((SKIPPED++)) || true continue From 710ad0ca3dcc69a8dfba7f086c722bc008c4bdc5 Mon Sep 17 00:00:00 2001 From: RuneBot14 Date: Sat, 31 Jan 2026 17:33:47 +0100 Subject: [PATCH 3/3] chore: trigger CI rebuild