From 96845fc48388c8a3940ae3a1409ce04841e95a57 Mon Sep 17 00:00:00 2001 From: William Durand Date: Mon, 30 Mar 2026 15:20:12 +0200 Subject: [PATCH 1/2] Switch to forked yara-x --- requirements/prod.txt | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/requirements/prod.txt b/requirements/prod.txt index b09d3586c6d2..1ec4ab416367 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -1668,14 +1668,6 @@ jsonschema-specifications==2025.9.1 \ drf-spectacular-sidecar==2026.3.1 \ --hash=sha256:5b7fedad66e3851f2f442480792c08115d79217959d01645b93d3d2258938be1 \ --hash=sha256:864edb83e022e13e3941c325c3cc0c954c843fa2e1d0bc95e81887664b2d3dad -yara-x==1.14.0 \ - --hash=sha256:0ab8b94caa6596ac72b7e0c9e91b8c053b18361b215f3dafe4d8261cbfb033a1 \ - --hash=sha256:4a1d6753ec52877ae136f11e32461d0d773844611f8761f8df7e8ff4197dcccf \ - --hash=sha256:52a0a943aa3bbf68a0ed9482ae19056021f92e8a197e96008c7cf7cf2c6cf921 \ - --hash=sha256:55f96cf0c3a87ff0f691ad6646bb6c973ad2990cc920fee67a25b65864785a11 \ - --hash=sha256:60e9bea642a41af74416ba93feeee9fa08f94787f9ea4ff3706aa1a7791e2afa \ - --hash=sha256:63264ca7814fed17303b641ebe2ff59924e73df62876ec06d5b31307e7b45adc \ - --hash=sha256:7e0bec7248480296e76d4c7cd1666380c847e7db93d7abd957d8ff994e3f31bf \ - --hash=sha256:dbae6139cbc4e03c9e2bc6bdc76bc26d55719a5cbf2e05eb93afa1e91a27d96b \ - --hash=sha256:e4686bfa0f57b8e77a94c5e0a8dbab56b76fc45d7e4a6524c7adb81a1316f00a \ - --hash=sha256:ec43a67f2d52ac06ae390a204ac5bde9a68a9d756521f9fec0274ae3080717f6 +# our own fork of yara-x +https://github.com/mozilla/yara-x/releases/download/2026.03.30/yara_x-1.14.0-cp38-abi3-manylinux_2_34_x86_64.whl \ + --hash=sha256:7373882d4865b20ee301ec968b9425e6ee2619fc5753af3520fccfd790586b9c From fcfc8ed7f99c5b58001b69d793ede696aff74dc9 Mon Sep 17 00:00:00 2001 From: William Durand Date: Mon, 30 Mar 2026 16:25:32 +0200 Subject: [PATCH 2/2] Pass options to yara-x --- src/olympia/scanners/tasks.py | 20 ++++++++++++++--- src/olympia/scanners/tests/test_tasks.py | 28 +++++++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/olympia/scanners/tasks.py b/src/olympia/scanners/tasks.py index 6501fecef911..eaccc061ed67 100644 --- a/src/olympia/scanners/tasks.py +++ b/src/olympia/scanners/tasks.py @@ -45,7 +45,7 @@ ) from olympia.devhub.tasks import validation_task from olympia.files.models import FileManifest, FileUpload -from olympia.files.utils import SafeZip +from olympia.files.utils import ManifestJSONExtractor, SafeZip from olympia.versions.models import Version from .models import ( @@ -523,6 +523,8 @@ def _run_yara_for_path(scanner_result, path, definition=None): # override them later when matching. externals = ScannerRule.get_yara_externals() + zip_file = SafeZip(source=path, ignore_filename_errors=True) + if waffle.switch_is_active('use-yara-x'): compiler = yara_x.Compiler() # Initialize the global variables (externals). @@ -533,6 +535,19 @@ def _run_yara_for_path(scanner_result, path, definition=None): # Create a scanner instance so that we can override the externals # per file (in the `_scan()` function). scanner = yara_x.Scanner(compiler.build()) + options = yara_x.ScanOptions() + options.set_module_metadata( + 'amo', + json.dumps( + { + 'manifest': ( + ManifestJSONExtractor(zip_file.read('manifest.json')).data + if zip_file.exists('manifest.json') + else {} + ) + } + ).encode('utf-8'), + ) def _scan(data, externals): for k, v in externals.items(): @@ -549,7 +564,7 @@ def _scan(data, externals): meta=dict(match.metadata), tags=match.tags, ) - for match in scanner.scan(data).matching_rules + for match in scanner.scan_with_options(data, options).matching_rules ] else: @@ -558,7 +573,6 @@ def _scan(data, externals): def _scan(data, externals): return rules.match(data=data, externals=externals) - zip_file = SafeZip(source=path, ignore_filename_errors=True) for zip_info in zip_file.info_list: if not zip_info.is_dir(): file_content = zip_file.read(zip_info) diff --git a/src/olympia/scanners/tests/test_tasks.py b/src/olympia/scanners/tests/test_tasks.py index 5e6d477117c3..df8adf8f6193 100644 --- a/src/olympia/scanners/tests/test_tasks.py +++ b/src/olympia/scanners/tests/test_tasks.py @@ -1746,7 +1746,33 @@ def test_run_in_binary_mode(self): @override_switch(name='use-yara-x', active=True) class TestRunYaraX(TestRunYara): - pass + def test_amo_module(self): + self.upload = self.get_upload('webextension.xpi') + rule = ScannerRule.objects.create( + name='match_id', + scanner=YARA, + definition=""" +import "amo" + +rule match_id { + condition: + amo.manifest.get_value("$.applications.gecko.id") == "@webextension-guid" + and not is_manifest_file +} + """, + ) + + run_yara(self.results, self.upload.pk) + + yara_results = ScannerResult.objects.all() + yara_result = yara_results[0] + assert yara_result.upload == self.upload + assert len(yara_result.results) == 1 + assert yara_result.results[0] == { + 'rule': rule.name, + 'tags': [], + 'meta': {'filename': 'index.js'}, + } class TestRunQueryRuleMixin: