Version in base suite: 1.3.4-1 Base version: suricata-update_1.3.4-1 Target version: suricata-update_1.3.4-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/s/suricata-update/suricata-update_1.3.4-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/s/suricata-update/suricata-update_1.3.4-1+deb13u1.dsc changelog | 7 ++ patches/CVE-2026-63347.patch | 133 +++++++++++++++++++++++++++++++++++++++++++ patches/series | 1 3 files changed, 141 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpjjlan7le/suricata-update_1.3.4-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpjjlan7le/suricata-update_1.3.4-1+deb13u1.dsc: no acceptable signature found diff -Nru suricata-update-1.3.4/debian/changelog suricata-update-1.3.4/debian/changelog --- suricata-update-1.3.4/debian/changelog 2024-12-13 22:34:57.000000000 +0000 +++ suricata-update-1.3.4/debian/changelog 2026-08-23 14:37:51.000000000 +0000 @@ -1,3 +1,10 @@ +suricata-update (1.3.4-1+deb13u1) trixie-security; urgency=medium + + * Fix CVE-2026-63347 in 1.3.4. + Cherry-Picked from fae50697dff60364d6f0638908c6762eec3b421c. + + -- Andreas Dolp Sun, 23 Aug 2026 16:37:51 +0200 + suricata-update (1.3.4-1) unstable; urgency=medium * New upstream release. diff -Nru suricata-update-1.3.4/debian/patches/CVE-2026-63347.patch suricata-update-1.3.4/debian/patches/CVE-2026-63347.patch --- suricata-update-1.3.4/debian/patches/CVE-2026-63347.patch 1970-01-01 00:00:00.000000000 +0000 +++ suricata-update-1.3.4/debian/patches/CVE-2026-63347.patch 2026-08-23 14:37:51.000000000 +0000 @@ -0,0 +1,133 @@ +From fae50697dff60364d6f0638908c6762eec3b421c Mon Sep 17 00:00:00 2001 +From: Jason Ish +Date: Fri, 26 Jun 2026 15:26:54 -0600 +Subject: [PATCH] fix: refuse to write files outside of data directory + +For example, an incoming rule archive may encode a filename name like +"rules/../../../../../../../etc/passwd". Before writing, expand to the +real path and make sure it falls inside the rule directory managed by +Suricata-Update, typically /var/lib/suricata/rules. + +If it lands outside this directory, refuse to extract and disable the rule with +a warning. + +Ticket: 8633 + +Origin: upstream, https://github.com/OISF/suricata-update/commit/fae50697dff60364d6f0638908c6762eec3b421c.patch +Bug: https://redmine.openinfosecfoundation.org/issues/8633 +Subject: Upstream fix for CVE-2026-63347 +--- + suricata/update/main.py | 25 ++++++++++++++++++++-- + tests/test_main.py | 47 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 70 insertions(+), 2 deletions(-) + +--- a/suricata/update/main.py ++++ b/suricata/update/main.py +@@ -494,6 +494,12 @@ + fp.write(dataset_contents.decode("utf-8")) + return new_rule + ++def is_path_in_directory(filename, directory): ++ relpath = os.path.relpath(filename, directory) ++ return relpath == os.curdir or ( ++ relpath != os.pardir and ++ not relpath.startswith(os.pardir + os.sep)) ++ + def handle_filehash_files(rule, dep_files, fhash): + if not rule.enabled: + return +@@ -512,14 +518,29 @@ + logger.debug("Copying %s file %s to output directory" % (fhash, filehash_fname)) + filepath = os.path.join(config.get_output_dir(), os.path.dirname(dest_filename)) + logger.debug("filepath: %s" % filepath) ++ output_filename = os.path.join(filepath, os.path.basename(filehash_fname)) ++ logger.debug("output fname: %s" % output_filename) ++ ++ # Refuse to write out source files that would land outside ++ # of the rule data directory (traversal attacks, etc). ++ # ++ # Also disable the rule. ++ output_dir = os.path.realpath(config.get_output_dir()) ++ real_output_filename = os.path.realpath(output_filename) ++ if not is_path_in_directory(real_output_filename, output_dir): ++ logger.warning( ++ "Refusing to write embedded %s file outside output directory " ++ "%s: %s (rule: %s). Rule will be disabled." % ( ++ fhash, output_dir, real_output_filename, rule.brief())) ++ rule.enabled = False ++ return ++ + try: + os.makedirs(filepath) + except OSError as oserr: + if oserr.errno != errno.EEXIST: + logger.error(oserr) + sys.exit(1) +- output_filename = os.path.join(filepath, os.path.basename(filehash_fname)) +- logger.debug("output fname: %s" % output_filename) + with open(output_filename, "w") as fp: + fp.write(dep_files[source_filename].decode("utf-8")) + +--- a/tests/test_main.py ++++ b/tests/test_main.py +@@ -19,6 +19,8 @@ + + import os + import io ++import shutil ++import tempfile + import unittest + + import suricata.update.rule +@@ -70,6 +72,51 @@ + r = fetch.check_checksum(local_file, net_arg) + self.assertTrue(r) + ++class EmbeddedFilesTestCase(unittest.TestCase): ++ ++ def setUp(self): ++ self.tmpdir = tempfile.mkdtemp() ++ self.output_dir = os.path.join(self.tmpdir, "rules") ++ self.previous_output = main.config.get(main.config.OUTPUT_KEY) ++ main.config.set(main.config.OUTPUT_KEY, self.output_dir) ++ ++ def tearDown(self): ++ if self.previous_output is None: ++ main.config._config.pop(main.config.OUTPUT_KEY, None) ++ else: ++ main.config.set(main.config.OUTPUT_KEY, self.previous_output) ++ shutil.rmtree(self.tmpdir) ++ ++ def test_handle_embedded_file_writes_inside_output_dir(self): ++ rule = suricata.update.rule.parse( ++ 'alert http any any -> any any (msg:"test"; ' ++ 'lua:scripts/payload.lua; sid:1; rev:1;)', ++ "rules/test.rules") ++ dep_files = { ++ "rules/scripts/payload.lua": b"return true", ++ } ++ ++ main.handle_filehash_files(rule, dep_files, "lua") ++ ++ self.assertTrue(rule.enabled) ++ with open(os.path.join(self.output_dir, "scripts", "payload.lua")) as fp: ++ self.assertEqual("return true", fp.read()) ++ ++ def test_handle_embedded_file_refuses_path_traversal(self): ++ rule = suricata.update.rule.parse( ++ 'alert http any any -> any any (msg:"test"; ' ++ 'lua:../outside/payload.lua; sid:1; rev:1;)', ++ "rules/test.rules") ++ dep_files = { ++ "rules/../outside/payload.lua": b"return true", ++ } ++ outside_dir = os.path.join(self.tmpdir, "outside") ++ ++ main.handle_filehash_files(rule, dep_files, "lua") ++ ++ self.assertFalse(rule.enabled) ++ self.assertFalse(os.path.exists(outside_dir)) ++ + class ThresholdProcessorTestCase(unittest.TestCase): + + processor = main.ThresholdProcessor() diff -Nru suricata-update-1.3.4/debian/patches/series suricata-update-1.3.4/debian/patches/series --- suricata-update-1.3.4/debian/patches/series 2021-11-23 08:38:00.000000000 +0000 +++ suricata-update-1.3.4/debian/patches/series 2026-08-23 14:37:51.000000000 +0000 @@ -1,3 +1,4 @@ remove-revision-update.patch python3-tests.patch no-suricata-python-package.patch +CVE-2026-63347.patch