Repository: DataDog/guarddog
Pull request #386 (2024-06-17 07:48:58)

Bugfix Bundled binary rule
The detection function reseting the detected items by mistake


Patch:
diff --git a/guarddog/analyzer/metadata/bundled_binary.py b/guarddog/analyzer/metadata/bundled_binary.py
index 310abed..a0d252c 100644
--- a/guarddog/analyzer/metadata/bundled_binary.py
+++ b/guarddog/analyzer/metadata/bundled_binary.py
@@ -35,9 +35,8 @@ class BundledBinary(Detector):
         if not path:
             raise ValueError("path is needed to run heuristic " + self.get_name())
 
+        bin_files = []
         for root, _, files in os.walk(path):
-            bin_files = []
-
             for f in files:
                 kind = self.is_binary(os.path.join(root, f))
                 if kind:


Test patch:
diff --git a/tests/analyzer/metadata/test_bundled_binary.py b/tests/analyzer/metadata/test_bundled_binary.py
index 40eb9e5..07f1845 100644
--- a/tests/analyzer/metadata/test_bundled_binary.py
+++ b/tests/analyzer/metadata/test_bundled_binary.py
@@ -3,52 +3,109 @@ import tempfile
 
 import pytest
 
+from guarddog.analyzer.metadata.bundled_binary import BundledBinary
 from guarddog.analyzer.metadata.npm import NPMBundledBinary
 from guarddog.analyzer.metadata.pypi import PypiBundledBinary
 from tests.analyzer.metadata.resources.sample_project_info import (
-    PYPI_PACKAGE_INFO,
-    generate_pypi_project_info,
-)
+    PYPI_PACKAGE_INFO, generate_pypi_project_info)
+
+pypi_detector = PypiBundledBinary()
+npm_detector = NPMBundledBinary()
 
 
 class TestBundleBinary:
-    pypi_detector = PypiBundledBinary()
-    npm_detector = NPMBundledBinary()
     nonempty_information = PYPI_PACKAGE_INFO
-    
+    binary_sample_exe = b"\x4D\x5A" + b"0x90" * 10  # exe magic number plus nop sled
+    binary_sample_elf = (
+        b"\x7F\x45\x4C\x46" + b"0x90" * 10
+    )  # elf magic number plus nop sled
 
-    def test_exe_npm(self):
+    @pytest.mark.parametrize(
+        "detector",
+        [
+            (pypi_detector),
+            (npm_detector),
+        ],
+    )
+    def test_exe(self, detector: BundledBinary):
         with tempfile.TemporaryDirectory() as dir:
             full_path = os.path.join(dir, "package")
             os.mkdir(full_path)
             with open(os.path.join(full_path, "windows.txt"), "wb") as f:
-                f.write(b"\x4D\x5A" + b"0x90"*10) # exe plus nop sled
-            matches, _ = self.npm_detector.detect({}, dir)
+                f.write(self.binary_sample_exe)
+            matches, _ = detector.detect({}, dir)
             assert matches
 
-    def test_elf_pypi(self):
+    @pytest.mark.parametrize(
+        "detector",
+        [
+            (pypi_detector),
+            (npm_detector),
+        ],
+    )
+    def test_elf(self, detector: BundledBinary):
         with tempfile.TemporaryDirectory() as dir:
             full_path = os.path.join(dir, "package")
             os.mkdir(full_path)
             with open(os.path.join(full_path, "linux.txt"), "wb") as f:
-                f.write(b"\x7F\x45\x4C\x46" + b"0x90"*10)
-            matches, _ = self.pypi_detector.detect({}, dir)
+                f.write(self.binary_sample_elf)
+            matches, _ = detector.detect({}, dir)
             assert matches
 
-    def test_plain(self):
+    @pytest.mark.parametrize(
+        "detector",
+        [
+            (pypi_detector),
+            (npm_detector),
+        ],
+    )
+    def test_plain(self, detector: BundledBinary):
         with tempfile.TemporaryDirectory() as dir:
             full_path = os.path.join(dir, "package")
             os.mkdir(full_path)
             with open(os.path.join(full_path, "file.exe"), "w") as f:
                 f.write("Hello world")
-            matches, _ = self.npm_detector.detect({}, dir)
+            matches, _ = detector.detect({}, dir)
             assert not matches
 
-    def test_empty(self):
+    @pytest.mark.parametrize(
+        "detector",
+        [
+            (pypi_detector),
+            (npm_detector),
+        ],
+    )
+    def test_empty(self, detector: BundledBinary):
         with tempfile.TemporaryDirectory() as dir:
             full_path = os.path.join(dir, "package")
             os.mkdir(full_path)
             with open(os.path.join(full_path, "some_file"), "w") as f:
                 pass
-            matches, _ = self.pypi_detector.detect({}, dir)
-            assert not matches
\ No newline at end of file
+            matches, _ = detector.detect({}, dir)
+            assert not matches
+
+    @pytest.mark.parametrize(
+        "detector",
+        [
+            (pypi_detector),
+            (npm_detector),
+        ],
+    )
+    def test_multiplebinaries(self, detector: BundledBinary):
+        with tempfile.TemporaryDirectory() as dir:
+            full_path1 = os.path.join(dir, "package")
+            os.mkdir(full_path1)
+            with open(os.path.join(full_path1, "file1"), "wb") as f:
+                f.write(self.binary_sample_elf)
+            full_path2 = os.path.join(full_path1, "nested")
+            os.mkdir(full_path2)
+            with open(os.path.join(full_path2, "file2"), "wb") as f:
+                f.write(self.binary_sample_exe)
+
+            matches, msg = detector.detect({}, dir)
+
+            assert matches
+            assert "file1" in msg
+            assert "exe" in msg
+            assert "file2" in msg
+            assert "elf" in msg