Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-configobj for openSUSE:Factory checked in at 2026-11-06 19:33:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-configobj (Old) and /work/SRC/openSUSE:Factory/.python-configobj.new.3759290 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-configobj" Fri Nov 6 19:33:38 2026 rev:27 rq:1395072 version:5.0.9 Changes: -------- --- /work/SRC/openSUSE:Factory/python-configobj/python-configobj.changes 2025-02-04 18:12:35.507683396 +0100 +++ /work/SRC/openSUSE:Factory/.python-configobj.new.3759290/python-configobj.changes 2026-11-06 19:36:34.341431450 +0100 @@ -1,0 +2,6 @@ +Thu Nov 5 04:03:35 UTC 2026 - Steve Kowalik <[email protected]> + +- CVE-2026-112300: Avoid ReDOS in section parsing. (bsc#1286097) + * Add patch CVE-2026-112300.patch + +------------------------------------------------------------------- @@ -179 +184,0 @@ - New: ---- CVE-2026-112300.patch ----------(New B)---------- New:- CVE-2026-112300: Avoid ReDOS in section parsing. (bsc#1286097) * Add patch CVE-2026-112300.patch ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-configobj.spec ++++++ --- /var/tmp/diff_new_pack.8yh3SG/_old 2026-11-06 19:36:35.526481019 +0100 +++ /var/tmp/diff_new_pack.8yh3SG/_new 2026-11-06 19:36:35.528481103 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-configobj # -# 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,10 +22,11 @@ Release: 0 Summary: Config file reading, writing and validation License: BSD-3-Clause -Group: Development/Languages/Python URL: https://github.com/DiffSK/configobj # No tests in PyPI sdist Source: https://github.com/DiffSK/configobj/archive/refs/tags/v%{version}.tar.gz#/configobj-%{version}-gh.tar.gz +# PATCH-FIX-OPENSUSE bsc#1286097 ReDoS in section marker parsing +Patch0: CVE-2026-112300.patch BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} BuildRequires: %{python_module wheel} ++++++ CVE-2026-112300.patch ++++++ Index: configobj-5.0.9/src/configobj/__init__.py =================================================================== --- configobj-5.0.9.orig/src/configobj/__init__.py +++ configobj-5.0.9/src/configobj/__init__.py @@ -1083,9 +1083,9 @@ class ConfigObj(Section): (\s*) # 1: indentation ((?:\[\s*)+) # 2: section marker open ( # 3: section name open - (?:"\s*\S.*?\s*")| # at least one non-space with double quotes - (?:'\s*\S.*?\s*')| # at least one non-space with single quotes - (?:[^'"\s].*?) # at least one non-space unquoted + (?:"\s*[^"\s][^"]*")| # at least one non-space/non-quote with double quotes (no internal quote/space backtracking) + (?:'\s*[^'\s][^']*')| # at least one non-space/non-quote with single quotes (no internal quote/space backtracking) + (?:[^\s\[\]](?:[^\]]*[^\s\]])?) # unquoted: starts after '['/spaces, contains no ']', ends on non-space before trailing \s* ) # section name close ((?:\s*\])+) # 4: section marker close \s*(\#.*)? # 5: optional comment Index: configobj-5.0.9/src/tests/test_cve_2026_112300.py =================================================================== --- /dev/null +++ configobj-5.0.9/src/tests/test_cve_2026_112300.py @@ -0,0 +1,106 @@ +import time +import pytest +from configobj import ConfigObj, ParseError, NestingError + + [email protected]( + "payload", + [ + # Vector 1: unquoted name + trailing spaces without closing ']' + "[a" + (" " * 50000), + # Vector 2: repeated opening brackets without closing ']' + "[" * 50000, + "[" * 25000 + "a" * 25000, + # Vector 3: double-quoted name with spaces and no closing ']' + '["a' + (" " * 50000) + '"', + # Vector 4: single-quoted name with spaces and no closing ']' + "['a" + (" " * 50000) + "'", + # Vector 5: alternating brackets/quotes/whitespace without ']' + "\t " + ("[ " * 15000) + ('" ' * 15000), + # Vector 6: closing ']' followed by non-comment trailing text (fails group 5) + "[a" + (" " * 20000) + ("b" * 20000) + "]trailing", + ], + ids=[ + "unquoted_trailing_spaces", + "repeated_open_brackets", + "open_brackets_and_chars", + "double_quoted_spaces", + "single_quoted_spaces", + "alternating_brackets_quotes", + "trailing_non_comment", + ], +) +def test_redos_vectors_complete_quickly(payload): + start = time.monotonic() + match = ConfigObj._sectionmarker.match(payload) + elapsed = time.monotonic() - start + + assert match is None + assert elapsed < 0.5, "ReDoS detected on payload starting with {!r} (took {:.2f}s)".format( + payload[:20], elapsed + ) + + [email protected]( + "line,expected", + [ + ("[section]", ("", "[", "section", "]", None)), + (" [section]", (" ", "[", "section", "]", None)), + ("[a]", ("", "[", "a", "]", None)), + ("[[subsection]]", ("", "[[", "subsection", "]]", None)), + ("[ [ spaced section ] ]", ("", "[ [ ", "spaced section", " ] ]", None)), + ('["quoted section"]', ("", "[", '"quoted section"', "]", None)), + ("['single quoted']", ("", "[", "'single quoted'", "]", None)), + ('["a"]', ("", "[", '"a"', "]", None)), + ('[" spaced quotes "]', ("", "[", '" spaced quotes "', "]", None)), + ('["brackets [inside] quotes"]', ("", "[", '"brackets [inside] quotes"', "]", None)), + ("['brackets [inside] quotes']", ("", "[", "'brackets [inside] quotes'", "]", None)), + ("[section] # inline comment", ("", "[", "section", "]", "# inline comment")), + ], +) +def test_valid_section_markers_preserved(line, expected): + mat = ConfigObj._sectionmarker.match(line) + assert mat is not None, "Failed to match valid line: {!r}".format(line) + assert mat.groups() == expected + + [email protected]( + "line", + [ + "[]", + "[ ]", + "[unclosed", + "[[unclosed", + "[section] trailing_junk", + ], +) +def test_invalid_section_markers_rejected(line): + assert ConfigObj._sectionmarker.match(line) is None, ( + "Unexpectedly matched invalid line: {!r}".format(line) + ) + + +def test_configobj_end_to_end_parsing(): + cfg = ConfigObj([ + "[main]", + "key = value", + " [[sub section]]", + ' [[["quoted ] subsection"]]]', + " subkey = subval", + ]) + assert cfg["main"]["key"] == "value" + assert cfg["main"]["sub section"]["quoted ] subsection"]["subkey"] == "subval" + + # Mismatched bracket counts still raise NestingError + with pytest.raises(NestingError): + ConfigObj(["[[mismatch]"], raise_errors=True) + + # Unclosed section header raises ParseError quickly + with pytest.raises(ParseError): + ConfigObj(["[a" + (" " * 50000)], raise_errors=True) + + [email protected]("empty_unquoted", ["[]", "[ ]"]) +def test_empty_unquoted_section_raises_parse_error(empty_unquoted): + with pytest.raises(ParseError): + ConfigObj([empty_unquoted], raise_errors=True)
