Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from pallets:main #18

Merged
merged 70 commits into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
f502aac
Add link to MarkupSafe in FAQ
matheusfelipeog Dec 1, 2022
9849db5
Add link to MarkupSafe project mentioned in FAQ (#1767)
davidism Dec 18, 2024
4e7850c
Clarify what operations the default Undefined supports
Varriount Mar 2, 2023
da67299
Clarify what operations the default "Undefined" supports (#1818)
davidism Dec 18, 2024
9c3622c
fix boolean error about whitespace control
hvassard Mar 3, 2023
058e059
fix boolean error about whitespace control (#1819)
davidism Dec 18, 2024
8a90b76
fix a typo in docs/templates.rst
xzmeng Aug 29, 2023
420082e
fix a typo in docs/templates.rst (#1881)
davidism Dec 18, 2024
7d023e5
Fix typo on filter name
vbuxbaum Nov 17, 2023
619d8ee
Fix typo on filter name (#1911)
davidism Dec 18, 2024
64a6bd1
improve clarity of logical bool ops
sirosen Feb 16, 2024
13c42b3
Slightly improve clarity of logical bool ops (#1938)
davidism Dec 18, 2024
75f0fbf
fix list comprehension example
lindhe Aug 12, 2024
a12789e
fix list comprehension example (#2017)
davidism Dec 18, 2024
c667d56
change "per default" to "by default"
davidism Dec 18, 2024
786d12b
clarify block outer scope docs
davidism Dec 18, 2024
3d0a7d7
clarify blocks docs (#2060)
davidism Dec 18, 2024
0c0a3d0
fix Jinja syntax in example
JamesParrott Dec 9, 2024
13ce60b
fix Jinja syntax in example (#2056)
davidism Dec 18, 2024
955d7da
Simplify example for ModuleLoader
charlax Jul 26, 2022
791dd3b
Simplify example for ModuleLoader (#1695)
davidism Dec 19, 2024
d3a0b1a
use env.concat when calling block reference
mkrizek Aug 9, 2022
a4abbfd
Use correct concat function for blocks evaluation (#1702)
davidism Dec 19, 2024
76af711
make unique filter async-aware
sileht Dec 23, 2022
20be10e
make unique filter async aware (#1782)
davidism Dec 19, 2024
2eb4542
int filter handles OverflowError to handle scientific notation
flpm May 20, 2024
3ef3ba8
fix how int filter handles scientific notation (#1984)
davidism Dec 19, 2024
4936e4d
make tuple unpacking deterministic in compiler
anentropic Sep 3, 2024
39d9fff
Make compiled output deterministic for tuple unpacking in set tag (#2…
davidism Dec 19, 2024
d4fb0e8
preserve `__slots__` on Undefined classes
nitzmahone Oct 1, 2024
ba8847a
Preserve `__slots__` metadata on Undefined types (#2026)
davidism Dec 19, 2024
7232b82
Fix pickle/copy support for the `missing` singleton
mattclay Oct 1, 2024
1dc04bc
Fix pickle/copy support for the `missing` singleton (#2029)
davidism Dec 19, 2024
b512058
sandbox disallows `clear` and `pop` on mutable sequence
dylanscott Oct 4, 2024
91e3521
sandbox disallows `clear` and `pop` on mutable sequence (#2033)
davidism Dec 19, 2024
0871c71
rearrange change entry
davidism Dec 19, 2024
91a972f
sandbox indirect calls to str.format
Lydxn2 Sep 23, 2024
48b0687
Merge commit from fork
davidism Dec 19, 2024
56a7246
fix f-string syntax error in code generation
sisp May 26, 2023
767b236
fix f-string syntax error in code generation (#1852)
davidism Dec 20, 2024
e45bc74
Bugfix: wrong default argument for `Environment.overlay(enable_async)…
SamyCookie Dec 19, 2024
b4b28ec
fix default for `Environment.overlay(enable_async)` (#2061)
davidism Dec 20, 2024
ed5f762
FileSystemLoader includes search paths in error
Yourun-proger May 2, 2022
227edfd
clean up message, add test
davidism Dec 20, 2024
58a358f
`FileSystemLoader` include paths in error (#1663)
davidism Dec 20, 2024
f54fa11
Improve the PackageLoader error message
LilyFoote Aug 11, 2022
aaa083d
separate messages, add test
davidism Dec 20, 2024
53c7591
Improve the PackageLoader error message (#1706)
davidism Dec 20, 2024
ded9915
improve annotations for methods returning copies
viccie30 Aug 23, 2023
106d61c
improve annotations for methods returning copies (#1880)
davidism Dec 20, 2024
0cd6948
don't apply `urlize` to `@a@b`
nabijaczleweli Jul 20, 2023
7a41ddb
don't apply `urlize` to `@a@b` (#2062)
davidism Dec 20, 2024
d05bd38
Pass context when using select
rgroothuijsen Nov 16, 2022
028f61d
Pass context to test when using select (#1762)
davidism Dec 20, 2024
ae68c96
document SandboxedNativeEnvironment pattern
davidism Dec 20, 2024
e7cb37d
document SandboxedNativeEnvironment pattern (#2063)
davidism Dec 20, 2024
d6998ab
Make ease of use update to template documentation
ratchek Dec 13, 2023
8a8eafc
edit block assignment section
davidism Dec 20, 2024
1d55cdd
Triple quotes in docs (#2064)
davidism Dec 20, 2024
ee83219
Add support for namespaces in tuple assignment
kevin-brown May 2, 2022
b8f4831
more comments about nsref assignment
davidism Dec 20, 2024
fbc3a69
Add support for namespaces in tuple parsing (#1664)
davidism Dec 20, 2024
66587ce
Fix bug where set would sometimes fail within if
kevin-brown May 2, 2022
c8fdce1
Fix bug involving calling set on a template parameter within all bran…
davidism Dec 21, 2024
eda8fe8
update dev dependencies
davidism Dec 21, 2024
8d58859
remove test pypi
davidism Dec 21, 2024
877f6e5
release version 3.1.5
davidism Dec 21, 2024
b4ffc8f
release version 3.1.5 (#2066)
davidism Dec 21, 2024
ab8218c
use project advisory link instead of global
davidism Dec 21, 2024
6aeab5d
Merge branch 'stable'
davidism Dec 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Version 3.1.5

Unreleased

- The sandboxed environment handles indirect calls to ``str.format``, such as
by passing a stored reference to a filter that calls its argument.
:ghsa:`q2x7-8rv6-6q7h`
- Sandbox does not allow ``clear`` and ``pop`` on known mutable sequence
types. :issue:`2032`
- Calling sync ``render`` for an async template uses ``asyncio.run``.
Expand Down
81 changes: 43 additions & 38 deletions src/jinja2/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from _string import formatter_field_name_split # type: ignore
from collections import abc
from collections import deque
from functools import update_wrapper
from string import Formatter

from markupsafe import EscapeFormatter
Expand Down Expand Up @@ -83,20 +84,6 @@
)


def inspect_format_method(callable: t.Callable[..., t.Any]) -> t.Optional[str]:
if not isinstance(
callable, (types.MethodType, types.BuiltinMethodType)
) or callable.__name__ not in ("format", "format_map"):
return None

obj = callable.__self__

if isinstance(obj, str):
return obj

return None


def safe_range(*args: int) -> range:
"""A range that can't generate ranges with a length of more than
MAX_RANGE items.
Expand Down Expand Up @@ -316,6 +303,9 @@ def getitem(
except AttributeError:
pass
else:
fmt = self.wrap_str_format(value)
if fmt is not None:
return fmt
if self.is_safe_attribute(obj, argument, value):
return value
return self.unsafe_undefined(obj, argument)
Expand All @@ -333,6 +323,9 @@ def getattr(self, obj: t.Any, attribute: str) -> t.Union[t.Any, Undefined]:
except (TypeError, LookupError):
pass
else:
fmt = self.wrap_str_format(value)
if fmt is not None:
return fmt
if self.is_safe_attribute(obj, attribute, value):
return value
return self.unsafe_undefined(obj, attribute)
Expand All @@ -348,34 +341,49 @@ def unsafe_undefined(self, obj: t.Any, attribute: str) -> Undefined:
exc=SecurityError,
)

def format_string(
self,
s: str,
args: t.Tuple[t.Any, ...],
kwargs: t.Dict[str, t.Any],
format_func: t.Optional[t.Callable[..., t.Any]] = None,
) -> str:
"""If a format call is detected, then this is routed through this
method so that our safety sandbox can be used for it.
def wrap_str_format(self, value: t.Any) -> t.Optional[t.Callable[..., str]]:
"""If the given value is a ``str.format`` or ``str.format_map`` method,
return a new function than handles sandboxing. This is done at access
rather than in :meth:`call`, so that calls made without ``call`` are
also sandboxed.
"""
if not isinstance(
value, (types.MethodType, types.BuiltinMethodType)
) or value.__name__ not in ("format", "format_map"):
return None

f_self: t.Any = value.__self__

if not isinstance(f_self, str):
return None

str_type: t.Type[str] = type(f_self)
is_format_map = value.__name__ == "format_map"
formatter: SandboxedFormatter
if isinstance(s, Markup):
formatter = SandboxedEscapeFormatter(self, escape=s.escape)

if isinstance(f_self, Markup):
formatter = SandboxedEscapeFormatter(self, escape=f_self.escape)
else:
formatter = SandboxedFormatter(self)

if format_func is not None and format_func.__name__ == "format_map":
if len(args) != 1 or kwargs:
raise TypeError(
"format_map() takes exactly one argument"
f" {len(args) + (kwargs is not None)} given"
)
vformat = formatter.vformat

def wrapper(*args: t.Any, **kwargs: t.Any) -> str:
if is_format_map:
if kwargs:
raise TypeError("format_map() takes no keyword arguments")

if len(args) != 1:
raise TypeError(
f"format_map() takes exactly one argument ({len(args)} given)"
)

kwargs = args[0]
args = ()

kwargs = args[0]
args = ()
return str_type(vformat(f_self, args, kwargs))

rv = formatter.vformat(s, args, kwargs)
return type(s)(rv)
return update_wrapper(wrapper, value)

def call(
__self, # noqa: B902
Expand All @@ -385,9 +393,6 @@ def call(
**kwargs: t.Any,
) -> t.Any:
"""Call an object from sandboxed code."""
fmt = inspect_format_method(__obj)
if fmt is not None:
return __self.format_string(fmt, args, kwargs, __obj)

# the double prefixes are to avoid double keyword argument
# errors when proxying the call.
Expand Down
17 changes: 17 additions & 0 deletions tests/test_security.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,20 @@ def test_safe_format_all_okay(self):
'{{ ("a{x.foo}b{y}"|safe).format_map({"x":{"foo": 42}, "y":"<foo>"}) }}'
)
assert t.render() == "a42b&lt;foo&gt;"

def test_indirect_call(self):
def run(value, arg):
return value.run(arg)

env = SandboxedEnvironment()
env.filters["run"] = run
t = env.from_string(
"""{% set
ns = namespace(run="{0.__call__.__builtins__[__import__]}".format)
%}
{{ ns | run(not_here) }}
"""
)

with pytest.raises(SecurityError):
t.render()