Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pybars3 for openSUSE:Factory 
checked in at 2026-11-09 16:05:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pybars3 (Old)
 and      /work/SRC/openSUSE:Factory/.python-pybars3.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pybars3"

Mon Nov  9 16:05:04 2026 rev:4 rq:1396213 version:0.9.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pybars3/python-pybars3.changes    
2025-06-04 20:29:22.791037382 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pybars3.new.3759290/python-pybars3.changes   
    2026-11-09 16:05:43.602536876 +0100
@@ -1,0 +2,6 @@
+Mon Nov  9 01:50:42 UTC 2026 - Steve Kowalik <[email protected]>
+
+- CVE-2026-119716: avoid code injection via bracketed paths (bsc#1289150)
+  * Add patch CVE-2026-119716.patch
+
+-------------------------------------------------------------------

New:
----
  CVE-2026-119716.patch

----------(New B)----------
  New:- CVE-2026-119716: avoid code injection via bracketed paths (bsc#1289150)
  * Add patch CVE-2026-119716.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pybars3.spec ++++++
--- /var/tmp/diff_new_pack.yjLY0e/_old  2026-11-09 16:05:44.734584335 +0100
+++ /var/tmp/diff_new_pack.yjLY0e/_new  2026-11-09 16:05:44.737584461 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pybars3
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -22,9 +22,10 @@
 Release:        0
 Summary:        Handlebarsjs templating for Python 3 and 2
 License:        LGPL-3.0-only
-Group:          Development/Languages/Python
 URL:            https://github.com/wbond/%{base_name}
 Source:         https://github.com/wbond/%{base_name}/archive/%{version}.tar.gz
+# PATCH-FIX-OPENSUSE bsc#1289150 avoid code injection via bracketed paths
+Patch0:         CVE-2026-119716.patch
 BuildRequires:  %{python_module PyMeta3 >= 0.5.1}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
@@ -41,7 +42,7 @@
 compatibility and numerous features from Handlebars.js 2.0.
 
 %prep
-%setup -q -n pybars3-%{version}
+%autosetup -p1 -n pybars3-%{version}
 
 %build
 %pyproject_wheel
@@ -57,5 +58,5 @@
 %license LICENSE
 %doc readme.md changelog.md
 %{python_sitelib}/pybars
-%{python_sitelib}/pybars3-%{version}*-info
+%{python_sitelib}/pybars3-%{version}.dist-info
 

++++++ CVE-2026-119716.patch ++++++
>From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Security Patch <[email protected]>
Date: Mon, 9 Nov 2026 12:43:00 +1100
Subject: [PATCH] Fix CVE-2026-119716: Escape bracketed path segments in
 compiler

pybars/_compiler.py did not escape quotes, backslashes, or newlines inside
bracketed path segments (`notclosebracket`), allowing crafted templates to
break out of generated Python string literals in `resolve()` and
`resolve_subexpr()` and execute arbitrary Python code.

Escape `\n`, `\r`, `\`, `'`, and `"` in `notclosebracket`, and remove the
obsolete `.replace('.get("', '').replace('")', '')` in `find_lookup` so a
trailing `\"` followed by `)` cannot be stripped into a dangling backslash.
---
 pybars/_compiler.py      | 11 ++++++++---
 tests/test_acceptance.py | 58 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 3 deletions(-)

Index: pybars3-0.9.7/pybars/_compiler.py
===================================================================
--- pybars3-0.9.7.orig/pybars/_compiler.py
+++ pybars3-0.9.7/pybars/_compiler.py
@@ -111,7 +111,12 @@ notsquote ::= <escapedquote>
     | (~("'") <anything>)
 escapedquote ::= '\\' '"' => '\\"'
     | "\\" "'" => "\\'"
-notclosebracket ::= (~(']') <anything>)
+notclosebracket ::= '\n' => '\\n'
+    | '\r' => '\\r'
+    | '\\' => '\\\\'
+    | '\'' => '\\\''
+    | '"' => '\\"'
+    | (~(']') <anything>)
 safesymbol ::=  ~<alt_inner> '['? (<letter>|'_'):start 
(<letterOrDigit>|'_')+:symbol ']'? => start + u''.join(symbol)
 symbol ::=  ~<alt_inner> '['? (<letterOrDigit>|'-'|'@')+:symbol ']'? => 
u''.join(symbol)
 partialname ::= <subexpression>:s => s
@@ -627,7 +632,7 @@ class CodeBuilder:
             # TODO: compile this whole expression in the grammar; for now,
             # fugly but only a compile time overhead.
             # XXX: just rm.
-            realname = path.replace('.get("', '').replace('")', '')
+            realname = path
             self._result.grow([
                 u"    value = helpers.get(u'%s')\n" % realname,
                 u"    if value is None:\n"
Index: pybars3-0.9.7/tests/test_acceptance.py
===================================================================
--- pybars3-0.9.7.orig/tests/test_acceptance.py
+++ pybars3-0.9.7/tests/test_acceptance.py
@@ -2703,3 +2703,61 @@ class TestAcceptance(TestCase):
         text = u"Hola {{name}}!"
         context = {'name': u"Samira"}
         self.assertRender(text, context, u"Hola Samira!")
+
+    def test_cve_2026_119716_bracketed_segment_code_injection(self):
+        executed = []
+
+        def side_effect():
+            executed.append(True)
+            return u"PWNED"
+
+        # 1. Simple bracketed path breakout attempt (single quotes)
+        tpl_simple = u"{{[a') or side_effect() or ('b]}}"
+        self.assertEqual(u"", render(tpl_simple, {'side_effect': side_effect}))
+
+        # 2. Complex dotted path breakout attempt
+        tpl_complex = u"{{foo.[a') or side_effect() or ('b]}}"
+        self.assertEqual(u"", render(tpl_complex, {'foo': {}, 'side_effect': 
side_effect}))
+
+        # 3. Helper / block argument bracketed path breakout attempt
+        helpers = {'echo': lambda this, val: val or u""}
+        tpl_arg = u"{{echo [a') or __import__('os').system('echo pwned') or 
('b]}}"
+        self.assertEqual(u"", render(tpl_arg, {}, helpers=helpers))
+
+        # 4. Subexpression helper name breakout attempt (double & single 
quotes)
+        tpl_subexpr_dq = u'{{echo ([a", context) or 
__import__("os").system("echo pwned") or ("b] 1)}}'
+        with self.assertRaises(PybarsError):
+            render(tpl_subexpr_dq, {}, helpers=helpers)
+
+        tpl_subexpr_sq = u"{{echo ([a', context) or 
__import__('os').system('echo pwned') or ('b] 1)}}"
+        with self.assertRaises(PybarsError):
+            render(tpl_subexpr_sq, {}, helpers=helpers)
+
+        # 5. Secondary gadget via trailing `")` and backslash escaping
+        tpl_gadget = u'{{[a")]}}{{[\')]}}'
+        self.assertEqual(u"", render(tpl_gadget, {}))
+
+        # 6. Newline injection inside bracketed path segment
+        tpl_newline = u"{{[a'\n" + u"    raise RuntimeError('injected')\n" + 
u"    ']}}"
+        self.assertEqual(u"", render(tpl_newline, {}))
+
+        self.assertEqual(executed, [])
+
+    def test_bracketed_segments_with_special_chars_resolve_correctly(self):
+        context = {
+            u"single'quote": u"val1",
+            u'double"quote': u"val2",
+            u"back\\slash": u"val3",
+            u'trailing")': u"val4",
+            u"nested": {
+                u"key'with\"quotes\\and\nnewline": u"val5"
+            }
+        }
+        self.assertEqual(u"val1", render(u"{{[single'quote]}}", context))
+        self.assertEqual(u"val2", render(u'{{[double"quote]}}', context))
+        self.assertEqual(u"val3", render(u"{{[back\\slash]}}", context))
+        self.assertEqual(u"val4", render(u'{{[trailing")]}}', context))
+        self.assertEqual(
+            u"val5",
+            render(u"{{nested.[key'with\"quotes\\and\nnewline]}}", context)
+        )

Reply via email to