|
| 1 | +From b289cbd6a87485ecf81bb959f11f177c71a2e041 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Kanishk-Bansal <kbkanishk975@gmail.com> |
| 3 | +Date: Fri, 7 Mar 2025 14:03:44 +0000 |
| 4 | +Subject: [PATCH] CVE-2025-27516 |
| 5 | + |
| 6 | +Upstream Reference : https://github.com/pallets/jinja/commit/90457bbf33b8662926ae65cdde4c4c32e756e403 |
| 7 | +--- |
| 8 | + src/jinja2/filters.py | 37 ++++++++++++++++--------------------- |
| 9 | + 1 file changed, 16 insertions(+), 21 deletions(-) |
| 10 | + |
| 11 | +diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py |
| 12 | +index ed07c4c..706d899 100644 |
| 13 | +--- a/src/jinja2/filters.py |
| 14 | ++++ b/src/jinja2/filters.py |
| 15 | +@@ -5,6 +5,7 @@ import re |
| 16 | + import typing |
| 17 | + import typing as t |
| 18 | + from collections import abc |
| 19 | ++from inspect import getattr_static |
| 20 | + from itertools import chain |
| 21 | + from itertools import groupby |
| 22 | + |
| 23 | +@@ -1373,31 +1374,25 @@ def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V] |
| 24 | + def do_attr( |
| 25 | + environment: "Environment", obj: t.Any, name: str |
| 26 | + ) -> t.Union[Undefined, t.Any]: |
| 27 | +- """Get an attribute of an object. ``foo|attr("bar")`` works like |
| 28 | +- ``foo.bar`` just that always an attribute is returned and items are not |
| 29 | +- looked up. |
| 30 | ++ """Get an attribute of an object. ``foo|attr("bar")`` works like |
| 31 | ++ ``foo.bar``, but returns undefined instead of falling back to ``foo["bar"]`` |
| 32 | ++ if the attribute doesn't exist. |
| 33 | + |
| 34 | + See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details. |
| 35 | + """ |
| 36 | ++ # Environment.getattr will fall back to obj[name] if obj.name doesn't exist. |
| 37 | ++ # But we want to call env.getattr to get behavior such as sandboxing. |
| 38 | ++ # Determine if the attr exists first, so we know the fallback won't trigger. |
| 39 | + try: |
| 40 | +- name = str(name) |
| 41 | +- except UnicodeError: |
| 42 | +- pass |
| 43 | +- else: |
| 44 | +- try: |
| 45 | +- value = getattr(obj, name) |
| 46 | +- except AttributeError: |
| 47 | +- pass |
| 48 | +- else: |
| 49 | +- if environment.sandboxed: |
| 50 | +- environment = t.cast("SandboxedEnvironment", environment) |
| 51 | +- |
| 52 | +- if not environment.is_safe_attribute(obj, name, value): |
| 53 | +- return environment.unsafe_undefined(obj, name) |
| 54 | +- |
| 55 | +- return value |
| 56 | +- |
| 57 | +- return environment.undefined(obj=obj, name=name) |
| 58 | ++ # This avoids executing properties/descriptors, but misses __getattr__ |
| 59 | ++ # and __getattribute__ dynamic attrs. |
| 60 | ++ getattr_static(obj, name) |
| 61 | ++ except AttributeError: |
| 62 | ++ # This finds dynamic attrs, and we know it's not a descriptor at this point. |
| 63 | ++ if not hasattr(obj, name): |
| 64 | ++ return environment.undefined(obj=obj, name=name) |
| 65 | ++ |
| 66 | ++ return environment.getattr(obj, name) |
| 67 | + |
| 68 | + |
| 69 | + @typing.overload |
| 70 | +-- |
| 71 | +2.45.2 |
| 72 | + |
0 commit comments