Package: release.debian.org Severity: normal Tags: trixie X-Debbugs-Cc: [email protected] Control: affects -1 + src:vitrage User: [email protected] Usertags: pu
Hi, [ Reason ] I'd like to address CVE-2026-28370, and the security team said it would be through p-u with no DSA. [ Impact ] CVE-2026-28370: Remote code execution through Vitrage query parser [ Tests ] Vitrage build process includes unit tests from upstream. [ Risks ] Not much, the patch is rather small, and upstream CI has functional tests. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable [ Changes ] Just upstream patch. Please allow me to upload Vitrage 14.0.0-4+deb13u1 to Trixie p-u. Cheers, Thomas Goirand (zigo)
diff -Nru vitrage-14.0.0/debian/changelog vitrage-14.0.0/debian/changelog --- vitrage-14.0.0/debian/changelog 2025-07-11 14:28:56.000000000 +0200 +++ vitrage-14.0.0/debian/changelog 2026-06-09 09:48:17.000000000 +0200 @@ -1,3 +1,11 @@ +vitrage (14.0.0-4+deb13u1) trixie; urgency=medium + + * CVE-2026-28370 / OSSA-2026-003: Remote code execution through Vitrage query + parser. Applied upstream patch "Replace eval with function matching". + (Closes: #1139452) + + -- Thomas Goirand <[email protected]> Tue, 09 Jun 2026 09:48:17 +0200 + vitrage (14.0.0-4) unstable; urgency=medium * Add export OS_OSLO_MESSAGING_RABBIT__PROCESSNAME for all daemons. diff -Nru vitrage-14.0.0/debian/patches/CVE-2026-28370_OSSA-2026-003_Replace_eval_with_function_matching.patch vitrage-14.0.0/debian/patches/CVE-2026-28370_OSSA-2026-003_Replace_eval_with_function_matching.patch --- vitrage-14.0.0/debian/patches/CVE-2026-28370_OSSA-2026-003_Replace_eval_with_function_matching.patch 1970-01-01 01:00:00.000000000 +0100 +++ vitrage-14.0.0/debian/patches/CVE-2026-28370_OSSA-2026-003_Replace_eval_with_function_matching.patch 2026-06-09 09:48:17.000000000 +0200 @@ -0,0 +1,147 @@ +Author: Dmitriy Rabotyagov <[email protected]> +Date: Tue, 30 Sep 2025 20:46:39 +0200 +Description: Replace eval with function matching + Using eval in code is not safe and may lead to security + risks, especially given that query itself is supplied by a user. + . + This refactors the code making is presumably safe + and prone to code injections, which are possible with eval. +Story: 2011539 +Task: 52866 +Bug-Debian: https://bugs.debian.org/1139452 +Change-Id: If629023052aa2c067c419bba10837f77bcc3e59c +Signed-off-by: Dmitriy Rabotyagov <[email protected]> +Origin: https://review.opendev.org/c/openstack/vitrage/+/962646 +Last-Update: 2026-06-09 + +diff --git a/releasenotes/notes/grap_query_eval_fixup-9232ce40ad85993e.yaml b/releasenotes/notes/grap_query_eval_fixup-9232ce40ad85993e.yaml +new file mode 100644 +index 0000000..9fa203a +--- /dev/null ++++ b/releasenotes/notes/grap_query_eval_fixup-9232ce40ad85993e.yaml +@@ -0,0 +1,5 @@ ++--- ++security: ++ - | ++ A security issue in the entity graph querying mechanism has been fixed. ++ This change hardens the query parser against malicious input. +diff --git a/vitrage/graph/query.py b/vitrage/graph/query.py +index c206a4c..c11cb46 100644 +--- a/vitrage/graph/query.py ++++ b/vitrage/graph/query.py +@@ -12,6 +12,7 @@ + # License for the specific language governing permissions and limitations + # under the License. + ++import operator + from oslo_log import log as logging + + from vitrage.common.exception import VitrageError +@@ -21,13 +22,21 @@ + operators = [ + '<', + '<=', +- # '=', + '==', + '!=', + '>=', + '>', + ] + ++ops = { ++ '<': operator.lt, ++ '<=': operator.le, ++ '==': operator.eq, ++ '!=': operator.ne, ++ '>=': operator.ge, ++ '>': operator.gt, ++} ++ + logical_operations = [ + 'and', + 'or' +@@ -64,10 +73,7 @@ + :return: a predicate "match(item)" + """ + try: +- expression = _create_query_expression(query=query_dict) +- LOG.debug('create_predicate::%s', expression) +- expression = 'lambda item: ' + expression +- return eval(expression) ++ return _create_query_function(query=query_dict) + except Exception as e: + LOG.error('invalid query format %s. Exception: %s', + query_dict, e) +@@ -75,46 +81,42 @@ + query_dict, e) + + +-def _create_query_expression(query, parent_operator=None): +- expressions = [] ++def _create_query_function(query, parent_operator=None): + + # First element or element under logical operation + if not parent_operator and isinstance(query, dict): + (key, value) = query.copy().popitem() +- return _create_query_expression(value, key) ++ return _create_query_function(value, key) + + # Continue recursion on logical (and/or) operation + elif parent_operator in logical_operations and isinstance(query, list): +- for val in query: +- expressions.append(_create_query_expression(val)) +- return _join_logical_operator(parent_operator, expressions) ++ predicates = [_create_query_function(val) for val in query] ++ ++ if not predicates: ++ return lambda item: False ++ ++ if parent_operator == 'and': ++ return lambda item: all(p(item) for p in predicates) ++ elif parent_operator == 'or': ++ return lambda item: any(p(item) for p in predicates) + + # Recursion evaluate leaf (stop condition) + elif parent_operator in operators: +- for key, val in query.items(): +- expressions.append('item.get(' + _evaluable_str(key) + ')' + +- parent_operator + ' ' + _evaluable_str(val)) +- return _join_logical_operator('and', expressions) ++ predicates = [] ++ op_func = ops[parent_operator] ++ for field, value in query.items(): ++ predicates.append( ++ lambda item, f=field, v=value: op_func(item.get(f), v) ++ ) ++ ++ # Multiple conditions under a comparison operator are implicitly 'and' ++ if len(predicates) > 1: ++ return lambda item: all(p(item) for p in predicates) ++ elif predicates: ++ return predicates[0] ++ else: ++ return lambda item: False ++ + else: + raise VitrageError('invalid partial query format', + parent_operator, query) +- +- +-def _evaluable_str(value): +- """wrap string/unicode with back tick""" +- if isinstance(value, str): +- return '\'' + value + '\'' +- else: +- return str(value) +- +- +-def _join_logical_operator(op, expressions): +- """Create an expressions string +- +- Example input: +- op='AND' +- expressions=['a == b', 'c < d'] +- Example output: (a == b AND c < d) +- """ +- separator = ' ' + op + ' ' +- return '(' + separator.join(expressions) + ')' diff -Nru vitrage-14.0.0/debian/patches/series vitrage-14.0.0/debian/patches/series --- vitrage-14.0.0/debian/patches/series 2025-07-11 14:28:56.000000000 +0200 +++ vitrage-14.0.0/debian/patches/series 2026-06-09 09:48:17.000000000 +0200 @@ -2,3 +2,4 @@ fix-oslo-config-generator.patch reproducible-build.patch remove-pysnmp-lextudio-from-requirements.patch +CVE-2026-28370_OSSA-2026-003_Replace_eval_with_function_matching.patch

