From 247de5e0c5062a792eb378e50e13e692885ee486 Mon Sep 17 00:00:00 2001 From: David Lord <davidism@gmail.com> Date: Tue, 14 Jan 2025 13:43:41 -0800 Subject: [PATCH 1/4] use global contributing guide Remove the per-project files so we don't have to keep them in sync. GitHub's UI links to everything except the contributing guide, so add a section about that to the readme. --- CONTRIBUTING.rst | 222 ----------------------------------------------- README.md | 8 ++ 2 files changed, 8 insertions(+), 222 deletions(-) delete mode 100644 CONTRIBUTING.rst diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 5f835032f..000000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,222 +0,0 @@ -How to contribute to Jinja -========================== - -Thank you for considering contributing to Jinja! - - -Support questions ------------------ - -Please don't use the issue tracker for this. The issue tracker is a -tool to address bugs and feature requests in Jinja itself. Use one of -the following resources for questions about using Jinja or issues with -your own code: - -- The ``#get-help`` channel on our Discord chat: - https://discord.gg/pallets -- The mailing list flask@python.org for long term discussion or larger - issues. -- Ask on `Stack Overflow`_. Search with Google first using: - ``site:stackoverflow.com jinja {search term, exception message, etc.}`` - -.. _Stack Overflow: https://stackoverflow.com/questions/tagged/jinja?tab=Frequent - - -Reporting issues ----------------- - -Include the following information in your post: - -- Describe what you expected to happen. -- If possible, include a `minimal reproducible example`_ to help us - identify the issue. This also helps check that the issue is not with - your own code. -- Describe what actually happened. Include the full traceback if there - was an exception. -- List your Python and Jinja versions. If possible, check if this - issue is already fixed in the latest releases or the latest code in - the repository. - -.. _minimal reproducible example: https://stackoverflow.com/help/minimal-reproducible-example - - -Submitting patches ------------------- - -If there is not an open issue for what you want to submit, prefer -opening one for discussion before working on a PR. You can work on any -issue that doesn't have an open PR linked to it or a maintainer assigned -to it. These show up in the sidebar. No need to ask if you can work on -an issue that interests you. - -Include the following in your patch: - -- Use `Black`_ to format your code. This and other tools will run - automatically if you install `pre-commit`_ using the instructions - below. -- Include tests if your patch adds or changes code. Make sure the test - fails without your patch. -- Update any relevant docs pages and docstrings. Docs pages and - docstrings should be wrapped at 72 characters. -- Add an entry in ``CHANGES.rst``. Use the same style as other - entries. Also include ``.. versionchanged::`` inline changelogs in - relevant docstrings. - -.. _Black: https://black.readthedocs.io -.. _pre-commit: https://pre-commit.com - - -First time setup -~~~~~~~~~~~~~~~~ - -- Download and install the `latest version of git`_. -- Configure git with your `username`_ and `email`_. - - .. code-block:: text - - $ git config --global user.name 'your name' - $ git config --global user.email 'your email' - -- Make sure you have a `GitHub account`_. -- Fork Jinja to your GitHub account by clicking the `Fork`_ button. -- `Clone`_ the main repository locally. - - .. code-block:: text - - $ git clone https://github.com/pallets/jinja - $ cd jinja - -- Add your fork as a remote to push your work to. Replace - ``{username}`` with your username. This names the remote "fork", the - default Pallets remote is "origin". - - .. code-block:: text - - $ git remote add fork https://github.com/{username}/jinja - -- Create a virtualenv. - - .. code-block:: text - - $ python3 -m venv env - $ . env/bin/activate - - On Windows, activating is different. - - .. code-block:: text - - > env\Scripts\activate - -- Upgrade pip and setuptools. - - .. code-block:: text - - $ python -m pip install --upgrade pip setuptools - -- Install the development dependencies, then install Jinja in editable - mode. - - .. code-block:: text - - $ pip install -r requirements/dev.txt && pip install -e . - -- Install the pre-commit hooks. - - .. code-block:: text - - $ pre-commit install - -.. _latest version of git: https://git-scm.com/downloads -.. _username: https://docs.github.com/en/github/using-git/setting-your-username-in-git -.. _email: https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address -.. _GitHub account: https://github.com/join -.. _Fork: https://github.com/pallets/jinja/fork -.. _Clone: https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#step-2-create-a-local-clone-of-your-fork - - -Start coding -~~~~~~~~~~~~ - -- Create a branch to identify the issue you would like to work on. If - you're submitting a bug or documentation fix, branch off of the - latest ".x" branch. - - .. code-block:: text - - $ git fetch origin - $ git checkout -b your-branch-name origin/3.0.x - - If you're submitting a feature addition or change, branch off of the - "main" branch. - - .. code-block:: text - - $ git fetch origin - $ git checkout -b your-branch-name origin/main - -- Using your favorite editor, make your changes, - `committing as you go`_. -- Include tests that cover any code changes you make. Make sure the - test fails without your patch. Run the tests as described below. -- Push your commits to your fork on GitHub and - `create a pull request`_. Link to the issue being addressed with - ``fixes #123`` in the pull request. - - .. code-block:: text - - $ git push --set-upstream fork your-branch-name - -.. _committing as you go: https://dont-be-afraid-to-commit.readthedocs.io/en/latest/git/commandlinegit.html#commit-your-changes -.. _create a pull request: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request - - -Running the tests -~~~~~~~~~~~~~~~~~ - -Run the basic test suite with pytest. - -.. code-block:: text - - $ pytest - -This runs the tests for the current environment, which is usually -sufficient. CI will run the full suite when you submit your pull -request. You can run the full test suite with tox if you don't want to -wait. - -.. code-block:: text - - $ tox - - -Running test coverage -~~~~~~~~~~~~~~~~~~~~~ - -Generating a report of lines that do not have test coverage can indicate -where to start contributing. Run ``pytest`` using ``coverage`` and -generate a report. - -.. code-block:: text - - $ pip install coverage - $ coverage run -m pytest - $ coverage html - -Open ``htmlcov/index.html`` in your browser to explore the report. - -Read more about `coverage <https://coverage.readthedocs.io>`__. - - -Building the docs -~~~~~~~~~~~~~~~~~ - -Build the docs in the ``docs`` directory using Sphinx. - -.. code-block:: text - - $ cd docs - $ make html - -Open ``_build/html/index.html`` in your browser to view the docs. - -Read more about `Sphinx <https://www.sphinx-doc.org/en/stable/>`__. diff --git a/README.md b/README.md index f4aa7cbea..d1a6870d0 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,11 @@ allow the maintainers to devote more time to the projects, [please donate today][]. [please donate today]: https://palletsprojects.com/donate + +## Contributing + +See our [detailed contributing documentation][contrib] for many ways to +contribute, including reporting issues, requesting features, asking or answering +questions, and making PRs. + +[contrib]: https://palletsprojects.com/contributing/ From 033c20015c7ca899ab52eb921bb0f08e6d3dd145 Mon Sep 17 00:00:00 2001 From: David Lord <davidism@gmail.com> Date: Wed, 5 Mar 2025 09:50:59 -0800 Subject: [PATCH 2/4] start version 3.1.6 --- CHANGES.rst | 5 +++++ src/jinja2/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index e1b339198..f1956ec12 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,5 +1,10 @@ .. currentmodule:: jinja2 +Version 3.1.6 +------------- + +Unreleased + Version 3.1.5 ------------- diff --git a/src/jinja2/__init__.py b/src/jinja2/__init__.py index d669f295b..e24d34fd2 100644 --- a/src/jinja2/__init__.py +++ b/src/jinja2/__init__.py @@ -35,4 +35,4 @@ from .utils import pass_eval_context as pass_eval_context from .utils import select_autoescape as select_autoescape -__version__ = "3.1.5" +__version__ = "3.1.6.dev" From 065334d1ee5b7210e1a0a93c37238c86858f2af7 Mon Sep 17 00:00:00 2001 From: David Lord <davidism@gmail.com> Date: Wed, 5 Mar 2025 10:08:48 -0800 Subject: [PATCH 3/4] attr filter uses env.getattr --- CHANGES.rst | 4 ++++ src/jinja2/filters.py | 37 ++++++++++++++++--------------------- tests/test_security.py | 10 ++++++++++ 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index f1956ec12..605a04fd9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,10 @@ Version 3.1.6 Unreleased +- The ``|attr`` filter does not bypass the environment's attribute lookup, + allowing the sandbox to apply its checks. :ghsa:`cpwx-vrp4-4pq7` + + Version 3.1.5 ------------- diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py index e5b5a00c5..2bcba4fbd 100644 --- a/src/jinja2/filters.py +++ b/src/jinja2/filters.py @@ -6,6 +6,7 @@ import typing import typing as t from collections import abc +from inspect import getattr_static from itertools import chain from itertools import groupby @@ -1411,31 +1412,25 @@ def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V] def do_attr( environment: "Environment", obj: t.Any, name: str ) -> t.Union[Undefined, t.Any]: - """Get an attribute of an object. ``foo|attr("bar")`` works like - ``foo.bar`` just that always an attribute is returned and items are not - looked up. + """Get an attribute of an object. ``foo|attr("bar")`` works like + ``foo.bar``, but returns undefined instead of falling back to ``foo["bar"]`` + if the attribute doesn't exist. See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details. """ + # Environment.getattr will fall back to obj[name] if obj.name doesn't exist. + # But we want to call env.getattr to get behavior such as sandboxing. + # Determine if the attr exists first, so we know the fallback won't trigger. try: - name = str(name) - except UnicodeError: - pass - else: - try: - value = getattr(obj, name) - except AttributeError: - pass - else: - if environment.sandboxed: - environment = t.cast("SandboxedEnvironment", environment) - - if not environment.is_safe_attribute(obj, name, value): - return environment.unsafe_undefined(obj, name) - - return value - - return environment.undefined(obj=obj, name=name) + # This avoids executing properties/descriptors, but misses __getattr__ + # and __getattribute__ dynamic attrs. + getattr_static(obj, name) + except AttributeError: + # This finds dynamic attrs, and we know it's not a descriptor at this point. + if not hasattr(obj, name): + return environment.undefined(obj=obj, name=name) + + return environment.getattr(obj, name) @typing.overload diff --git a/tests/test_security.py b/tests/test_security.py index 864d5f7f9..3a1378192 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -190,3 +190,13 @@ def run(value, arg): with pytest.raises(SecurityError): t.render() + + def test_attr_filter(self) -> None: + env = SandboxedEnvironment() + t = env.from_string( + """{{ "{0.__call__.__builtins__[__import__]}" + | attr("format")(not_here) }}""" + ) + + with pytest.raises(SecurityError): + t.render() From 15206881c006c79667fe5154fe80c01c65410679 Mon Sep 17 00:00:00 2001 From: David Lord <davidism@gmail.com> Date: Wed, 5 Mar 2025 11:51:17 -0800 Subject: [PATCH 4/4] release version 3.1.6 --- CHANGES.rst | 2 +- src/jinja2/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 605a04fd9..2844c4c01 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,7 +3,7 @@ Version 3.1.6 ------------- -Unreleased +Released 2025-03-05 - The ``|attr`` filter does not bypass the environment's attribute lookup, allowing the sandbox to apply its checks. :ghsa:`cpwx-vrp4-4pq7` diff --git a/src/jinja2/__init__.py b/src/jinja2/__init__.py index e24d34fd2..1a423a3ea 100644 --- a/src/jinja2/__init__.py +++ b/src/jinja2/__init__.py @@ -35,4 +35,4 @@ from .utils import pass_eval_context as pass_eval_context from .utils import select_autoescape as select_autoescape -__version__ = "3.1.6.dev" +__version__ = "3.1.6"