diff --git a/django/__init__.py b/django/__init__.py index c4b31bd522f6..100b36676849 100644 --- a/django/__init__.py +++ b/django/__init__.py @@ -1,6 +1,6 @@ from django.utils.version import get_version -VERSION = (3, 1, 13, 'final', 0) +VERSION = (3, 1, 14, 'final', 0) __version__ = get_version(VERSION) diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py index e565d34b2733..abf0a11572e8 100644 --- a/django/urls/resolvers.py +++ b/django/urls/resolvers.py @@ -153,7 +153,11 @@ def __init__(self, regex, name=None, is_endpoint=False): self.converters = {} def match(self, path): - match = self.regex.search(path) + match = ( + self.regex.fullmatch(path) + if self._is_endpoint and self.regex.pattern.endswith('$') + else self.regex.search(path) + ) if match: # If there are any named groups, use those as kwargs, ignoring # non-named groups. Otherwise, pass all non-named arguments as @@ -240,7 +244,7 @@ def _route_to_regex(route, is_endpoint=False): converters[parameter] = converter parts.append('(?P<' + parameter + '>' + converter.regex + ')') if is_endpoint: - parts.append('$') + parts.append(r'\Z') return ''.join(parts), converters diff --git a/docs/conf.py b/docs/conf.py index d3c09110da52..b47e2972758b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -241,7 +241,6 @@ def django_release(): # Appended to every page rst_epilog = """ .. |django-users| replace:: :ref:`django-users ` -.. |django-core-mentorship| replace:: :ref:`django-core-mentorship ` .. |django-developers| replace:: :ref:`django-developers ` .. |django-announce| replace:: :ref:`django-announce ` .. |django-updates| replace:: :ref:`django-updates ` diff --git a/docs/internals/mailing-lists.txt b/docs/internals/mailing-lists.txt index d5b9ab5f9ced..cdf5b6d26451 100644 --- a/docs/internals/mailing-lists.txt +++ b/docs/internals/mailing-lists.txt @@ -35,23 +35,6 @@ installation, usage, or debugging of Django. .. _django-users subscription email address: mailto:django-users+subscribe@googlegroups.com .. _django-users posting email: mailto:django-users@googlegroups.com -.. _django-core-mentorship-mailing-list: - -``django-core-mentorship`` -========================== - -The Django Core Mentorship list is intended to provide a welcoming -introductory environment for community members interested in contributing to -the Django Project. - -* `django-core-mentorship mailing archive`_ -* `django-core-mentorship subscription email address`_ -* `django-core-mentorship posting email`_ - -.. _django-core-mentorship mailing archive: https://groups.google.com/d/forum/django-core-mentorship -.. _django-core-mentorship subscription email address: mailto:django-core-mentorship+subscribe@googlegroups.com -.. _django-core-mentorship posting email: mailto:django-core-mentorship@googlegroups.com - .. _django-developers-mailing-list: ``django-developers`` diff --git a/docs/internals/organization.txt b/docs/internals/organization.txt index b2d399255f66..b124b4b5fe93 100644 --- a/docs/internals/organization.txt +++ b/docs/internals/organization.txt @@ -21,170 +21,280 @@ and its community. .. _Django Code of Conduct: https://www.djangoproject.com/conduct/ .. _Django Software Foundation: https://www.djangoproject.com/foundation/ -The Django core team makes the decisions, nominates its new members, and -elects its technical board. While it holds decision power in theory, it aims -at using it as rarely as possible in practice. Rough consensus should be the -norm and formal voting an exception. +.. _mergers-team: -.. _core-team: - -Core team -========= +Mergers +======= Role ---- -The core team is the group of trusted volunteers who manage the Django -Project. They assume many roles required to achieve the project's goals, -especially those that require a high level of trust. They make the decisions -that shape the future of the project. - -Core team members are expected to act as role models for the community and -custodians of the project, on behalf of the community and all those who rely -on Django. - -They will intervene, where necessary, in online discussions or at official -Django events on the rare occasions that a situation arises that requires -intervention. - -They have authority over the Django Project infrastructure, including the -Django Project website itself, the Django GitHub organization and -repositories, the Trac bug tracker, the mailing lists, IRC channels, etc. +Mergers_ are a small set of people who merge pull requests to the `Django Git +repository`_. Prerogatives ------------ -Core team members may participate in formal votes, typically to nominate new -team members and to elect the technical board. +Mergers hold the following prerogatives: -Some contributions don't require commit access. Depending on the reasons why a -contributor joins the team, they may or may not have commit permissions to the -Django code repository. +- Merging any pull request which constitutes a `minor change`_ (small enough + not to require the use of the `DEP process`_). A Merger must not merge a + change primarily authored by that Merger, unless the pull request has been + approved by: -However, should the need arise, any team member may ask for commit access by -writing to the core team's mailing list. Access will be granted unless the -person withdraws their request or the technical board vetoes the proposal. + - another Merger, + - a technical board member, + - a member of the `triage & review team`_, or + - a member of the `security team`_. -Core team members who have commit access are referred to as "committers" or -"core developers". +- Initiating discussion of a minor change in the appropriate venue, and request + that other Mergers refrain from merging it while discussion proceeds. +- Requesting a vote of the technical board regarding any minor change if, in + the Merger's opinion, discussion has failed to reach a consensus. +- Requesting a vote of the technical board when a `major change`_ (significant + enough to require the use of the `DEP process`_) reaches one of its + implementation milestones and is intended to merge. -Other permissions, such as access to the servers, are granted to those who -need them through the same process. +.. _`minor change`: https://github.com/django/deps/blob/main/accepted/0010-new-governance.rst#terminology +.. _`major change`: https://github.com/django/deps/blob/main/accepted/0010-new-governance.rst#terminology Membership ---------- -`Django team members `_ -demonstrate: - -- a good grasp of the philosophy of the Django Project -- a solid track record of being constructive and helpful -- significant contributions to the project's goals, in any form -- willingness to dedicate some time to improving Django - -As the project matures, contributions go way beyond code. Here's an incomplete -list of areas where contributions may be considered for joining the core team, -in no particular order: - -- Working on community management and outreach -- Providing support on the mailing-lists and on IRC -- Triaging tickets -- Writing patches (code, docs, or tests) -- Reviewing patches (code, docs, or tests) -- Participating in design decisions -- Providing expertise in a particular domain (security, i18n, etc.) -- Managing the continuous integration infrastructure -- Managing the servers (website, tracker, documentation, etc.) -- Maintaining related projects (djangoproject.com site, ex-contrib apps, etc.) -- Creating visual designs - -Very few areas are reserved to core team members: - -- Reviewing security reports -- Merging patches (code, docs, or tests) -- Packaging releases - -Core team membership acknowledges sustained and valuable efforts that align -well with the philosophy and the goals of the Django Project. - -It is granted by a four fifths majority of votes cast in a core team vote and -no veto by the technical board. - -Core team members are always looking for promising contributors, teaching them -how the project is managed, and submitting their names to the core team's vote -when they're ready. If you would like to join the core team, you can contact a -core team member privately or ask for guidance on the :ref:`Django Core -Mentorship mailing-list `. - -There's no time limit on core team membership. However, in order to provide -the general public with a reasonable idea of how many people maintain Django, -core team members who have stopped contributing are encouraged to declare -themselves as "past team members". Those who haven't made any non-trivial -contribution in two years may be asked to move themselves to this category, -and moved there if they don't respond. Past team members lose their privileges -such as voting rights and commit access. +`The technical board`_ selects Mergers_ as necessary to maintain their number +at a minimum of three, in order to spread the workload and avoid over-burdening +or burning out any individual Merger. There is no upper limit to the number of +Mergers. -.. _technical-board: +It's not a requirement that a Merger is also a Django Fellow, but the Django +Software Foundation has the power to use funding of Fellow positions as a way +to make the role of Merger sustainable. -Technical board -=============== +The following restrictions apply to the role of Merger: + +- A person must not simultaneously serve as a member of the technical board. If + a Merger is elected to the technical board, they shall cease to be a Merger + immediately upon taking up membership in the technical board. +- A person may serve in the roles of Releaser and Merger simultaneously. + +The selection process, when a vacancy occurs or when the technical board deems +it necessary to select additional persons for such a role, occur as follows: + +- Any member in good standing of an appropriate discussion venue, or the Django + Software Foundation board acting with the input of the DSF's Fellowship + committee, may suggest a person for consideration. +- The technical board considers the suggestions put forth, and then any member + of the technical board formally nominates a candidate for the role. +- The technical board votes on nominees. + +Mergers may resign their role at any time, but should endeavor to provide some +advance notice in order to allow the selection of a replacement. Termination of +the contract of a Django Fellow by the Django Software Foundation temporarily +suspends that person's Merger role until such time as the technical board can +vote on their nomination. + +Otherwise, a Merger may be removed by: + +- Becoming disqualified due to election to the technical board. +- Becoming disqualified due to actions taken by the Code of Conduct committee + of the Django Software Foundation. +- A vote of the technical board. + +.. _releasers-team: + +Releasers +========= Role ---- -The technical board is a group of experienced and active committers who steer -technical choices. Their main concern is to maintain the quality and stability -of the Django Web Framework. +Releasers_ are a small set of people who have the authority to upload packaged +releases of Django to the `Python Package Index`_, and to the +`djangoproject.com`_ website. Prerogatives ------------ -The technical board holds two prerogatives: +Releasers_ :doc:`build Django releases ` and +upload them to the `Python Package Index`_, and to the `djangoproject.com`_ +website. + +Membership +---------- + +`The technical board`_ selects Releasers_ as necessary to maintain their number +at a minimum of three, in order to spread the workload and avoid over-burdening +or burning out any individual Releaser. There is no upper limit to the number +of Releasers. -- Making major technical decisions when no consensus is found otherwise. This - happens on the |django-developers| mailing-list. -- Veto a grant of commit access or remove commit access. This happens on the - ``django-core`` mailing-list. +It's not a requirement that a Releaser is also a Django Fellow, but the Django +Software Foundation has the power to use funding of Fellow positions as a way +to make the role of Releaser sustainable. -In both cases, the technical board is a last resort. In these matters, it -fulfills a similar function to the former Benevolent Dictators For Life. +A person may serve in the roles of Releaser and Merger simultaneously. -When the board wants to exercise one of these prerogatives, it must hold a -private, simple majority vote on the resolution. The quorum is the full -committee — each member must cast a vote or abstain explicitly. Then the board -communicates the result, and if possible the reasons, on the appropriate -mailing-list. There's no appeal for such decisions. +The selection process, when a vacancy occurs or when the technical board deems +it necessary to select additional persons for such a role, occur as follows: -In addition, at its discretion, the technical board may act in an advisory -capacity on non-technical decisions. +- Any member in good standing of an appropriate discussion venue, or the Django + Software Foundation board acting with the input of the DSF's Fellowship + committee, may suggest a person for consideration. +- The technical board considers the suggestions put forth, and then any member + of the technical board formally nominates a candidate for the role. +- The technical board votes on nominees. -Membership ----------- +Releasers may resign their role at any time, but should endeavor to provide +some advance notice in order to allow the selection of a replacement. +Termination of the contract of a Django Fellow by the Django Software +Foundation temporarily suspends that person's Releaser role until such time as +the technical board can vote on their nomination. + +Otherwise, a Releaser may be removed by: -`The technical board`_ is an elected group of five committers. They're expected -to be experienced but there's no formal seniority requirement. +- Becoming disqualified due to actions taken by the Code of Conduct committee + of the Django Software Foundation. +- A vote of the technical board. -A new board is elected after each feature release of Django. The election -process is managed by a returns officer nominated by the outgoing technical -board. The election process works as follows: +.. _`Python Package Index`: https://pypi.org/project/Django/ +.. _djangoproject.com: https://www.djangoproject.com/download/ -#. Candidates advertise their application for the technical board to the team. +.. _technical-board: - They must be committers already. There's no term limit for technical board - members. +Technical board +=============== -#. Each team member can vote for zero to five people among the candidates. - Candidates are ranked by the total number of votes they received. +Role +---- - In case of a tie, the person who joined the core team earlier wins. +The technical board is a group of experienced contributors who: -Both the application and the voting period last between one and two weeks, at -the outgoing board's discretion. +- provide oversight of Django's development and release process, +- assist in setting the direction of feature development and releases, +- take part in filling certain roles, and +- have a tie-breaking vote when other decision-making processes fail. -.. _the technical board: https://www.djangoproject.com/foundation/teams/#technical-board-team +Their main concern is to maintain the quality and stability of the Django Web +Framework. + +Prerogatives +------------ + +The technical board holds the following prerogatives: + +- Making a binding decision regarding any question of a technical change to + Django. +- Vetoing the merging of any particular piece of code into Django or ordering + the reversion of any particular merge or commit. +- Announcing calls for proposals and ideas for the future technical direction + of Django. +- Setting and adjusting the schedule of releases of Django. +- Selecting and removing mergers and releasers. +- Participating in the removal of members of the technical board, when deemed + appropriate. +- Calling elections of the technical board outside of those which are + automatically triggered, at times when the technical board deems an election + is appropriate. +- Participating in modifying Django's governance (see + :ref:`organization-change`). +- Declining to vote on a matter the technical board feels is unripe for a + binding decision, or which the technical board feels is outside the scope of + its powers. +- Taking charge of the governance of other technical teams within the Django + open-source project, and governing those teams accordingly. + +Membership +---------- + +`The technical board`_ is an elected group of five experienced contributors +who demonstrate: + +- A history of technical contributions to Django or the Django ecosystem. This + history must begin at least 18 months prior to the individual's candidacy for + the technical board. +- A history of participation in Django's development outside of contributions + merged to the `Django Git repository`_. This may include, but is not + restricted to: + + - Participation in discussions on the |django-developers| mailing list or + the `Django forum`_. + - Reviewing and offering feedback on pull requests in the Django source-code + repository. + - Assisting in triage and management of the Django bug tracker. + +- A history of recent engagement with the direction and development of Django. + Such engagement must have occurred within a period of no more than two years + prior to the individual's candidacy for the technical board. + +A new board is elected after each release cycle of Django. The election process +works as follows: + +#. The technical board direct one of its members to notify the Secretary of the + Django Software Foundation, in writing, of the triggering of the election, + and the condition which triggered it. The Secretary post to the appropriate + venue -- the |django-developers| mailing list and the `Django forum`_ to + announce the election and its timeline. +#. As soon as the election is announced, the `DSF Board`_ begin a period of + voter registration. All `individual members of the DSF`_ are automatically + registered and need not explicitly register. All other persons who believe + themselves eligible to vote, but who have not yet registered to vote, may + make an application to the DSF Board for voting privileges. The voter + registration form and roll of voters is maintained by the DSF Board. The DSF + Board may challenge and reject the registration of voters it believes are + registering in bad faith or who it believes have falsified their + qualifications or are otherwise unqualified. +#. Registration of voters close one week after the announcement of the + election. At that point, registration of candidates begin. Any qualified + person may register as a candidate. The candidate registration form and + roster of candidates are maintained by the DSF Board, and candidates must + provide evidence of their qualifications as part of registration. The DSF + Board may challenge and reject the registration of candidates it believes do + not meet the qualifications of members of the Technical Board, or who it + believes are registering in bad faith. +#. Registration of candidates close one week after it has opened. One week + after registration of candidates closes, the Secretary of the DSF publish + the roster of candidates to the |django-developers| mailing list and the + `Django forum`_, and the election begin. The DSF Board provide a voting form + accessible to registered voters, and is the custodian of the votes. +#. Voting is by secret ballot containing the roster of candidates, and any + relevant materials regarding the candidates, in a randomized order. Each + voter may vote for up to five candidates on the ballot. +#. The election conclude one week after it begins. The DSF Board then tally the + votes and produce a summary, including the total number of votes cast and + the number received by each candidate. This summary is ratified by a + majority vote of the DSF Board, then posted by the Secretary of the DSF to + the |django-developers| mailing list and the Django Forum. The five + candidates with the highest vote totals are immediately become the new + technical board. + +A member of the technical board may be removed by: + +- Becoming disqualified due to actions taken by the Code of Conduct committee + of the Django Software Foundation. +- Determining that they did not possess the qualifications of a member of the + technical board. This determination must be made jointly by the other members + of the technical board, and the `DSF Board`_. A valid determination of + ineligibility requires that all other members of the technical board and all + members of the DSF Board vote who can vote on the issue (the affected person, + if a DSF Board member, must not vote) vote "yes" on a motion that the person + in question is ineligible. + +.. _`Django forum`: https://forum.djangoproject.com/ +.. _`Django Git repository`: https://github.com/django/django/ +.. _`DSF Board`: https://www.djangoproject.com/foundation/#board +.. _`individual members of the DSF`: https://www.djangoproject.com/foundation/individual-members/ +.. _mergers: https://www.djangoproject.com/foundation/teams/#mergers-team +.. _releasers: https://www.djangoproject.com/foundation/teams/#releasers-team +.. _`security team`: https://www.djangoproject.com/foundation/teams/#security-team +.. _`the technical board`: https://www.djangoproject.com/foundation/teams/#technical-board-team +.. _`triage & review team`: https://www.djangoproject.com/foundation/teams/#triage-review-team + +.. _organization-change: Changing the organization ========================= -Changes to this document require a four fifths majority of votes cast in a -core team vote and no veto by the technical board. +Changes to this document require the use of the `DEP process`_, with +modifications described in `DEP 0010`_. + +.. _`DEP process`: https://github.com/django/deps/blob/main/final/0001-dep-process.rst +.. _`DEP 0010`: https://github.com/django/deps/blob/main/accepted/0010-new-governance.rst#changing-this-governance-process diff --git a/docs/releases/2.2.25.txt b/docs/releases/2.2.25.txt new file mode 100644 index 000000000000..1662451a3064 --- /dev/null +++ b/docs/releases/2.2.25.txt @@ -0,0 +1,13 @@ +=========================== +Django 2.2.25 release notes +=========================== + +*December 7, 2021* + +Django 2.2.25 fixes a security issue with severity "low" in 2.2.24. + +CVE-2021-44420: Potential bypass of an upstream access control based on URL paths +================================================================================= + +HTTP requests for URLs with trailing newlines could bypass an upstream access +control based on URL paths. diff --git a/docs/releases/3.1.13.txt b/docs/releases/3.1.13.txt index af8ccec5357b..b4cc930ec668 100644 --- a/docs/releases/3.1.13.txt +++ b/docs/releases/3.1.13.txt @@ -4,7 +4,7 @@ Django 3.1.13 release notes *July 1, 2021* -Django 3.1.13 fixes a security issues with severity "high" in 3.1.12. +Django 3.1.13 fixes a security issue with severity "high" in 3.1.12. CVE-2021-35042: Potential SQL injection via unsanitized ``QuerySet.order_by()`` input ===================================================================================== diff --git a/docs/releases/3.1.14.txt b/docs/releases/3.1.14.txt new file mode 100644 index 000000000000..fb6fef88842d --- /dev/null +++ b/docs/releases/3.1.14.txt @@ -0,0 +1,13 @@ +=========================== +Django 3.1.14 release notes +=========================== + +*December 7, 2021* + +Django 3.1.14 fixes a security issue with severity "low" in 3.1.13. + +CVE-2021-44420: Potential bypass of an upstream access control based on URL paths +================================================================================= + +HTTP requests for URLs with trailing newlines could bypass an upstream access +control based on URL paths. diff --git a/docs/releases/index.txt b/docs/releases/index.txt index e54a30f5a17b..973e43bd2cc3 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -25,6 +25,7 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 3.1.14 3.1.13 3.1.12 3.1.11 @@ -66,6 +67,7 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 2.2.25 2.2.24 2.2.23 2.2.22 diff --git a/docs/releases/security.txt b/docs/releases/security.txt index 4d9096856297..55f91b28e1a1 100644 --- a/docs/releases/security.txt +++ b/docs/releases/security.txt @@ -1230,3 +1230,16 @@ Versions affected * Django 3.2 :commit:`(patch) <9f75e2e562fa0c0482f3dde6fc7399a9070b4a3d>` * Django 3.1 :commit:`(patch) <203d4ab9ebcd72fc4d6eb7398e66ed9e474e118e>` * Django 2.2 :commit:`(patch) ` + +July 1, 2021 - :cve:`2021-35042` +-------------------------------- + +Potential SQL injection via unsanitized ``QuerySet.order_by()`` input. `Full +description +`__ + +Versions affected +~~~~~~~~~~~~~~~~~ + +* Django 3.2 :commit:`(patch) ` +* Django 3.1 :commit:`(patch) <0bd57a879a0d54920bb9038a732645fb917040e9>` diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index 856680371510..8942117543da 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -222,6 +222,7 @@ flatpages Flatpages followup fooapp +formatter formatters formfield formset diff --git a/tests/urlpatterns/tests.py b/tests/urlpatterns/tests.py index 54b7e0981331..98866f0b7934 100644 --- a/tests/urlpatterns/tests.py +++ b/tests/urlpatterns/tests.py @@ -147,6 +147,19 @@ def test_space_in_route(self): with self.assertRaisesMessage(ImproperlyConfigured, msg): path('space/', empty_view) + def test_path_trailing_newlines(self): + tests = [ + '/articles/2003/\n', + '/articles/2010/\n', + '/en/foo/\n', + '/included_urls/extra/\n', + '/regex/1/\n', + '/users/1/\n', + ] + for url in tests: + with self.subTest(url=url), self.assertRaises(Resolver404): + resolve(url) + @override_settings(ROOT_URLCONF='urlpatterns.converter_urls') class ConverterTests(SimpleTestCase): diff --git a/tests/user_commands/tests.py b/tests/user_commands/tests.py index 0a3b6ae77ebf..ff600d986ee3 100644 --- a/tests/user_commands/tests.py +++ b/tests/user_commands/tests.py @@ -241,7 +241,7 @@ def test_subparser_dest_required_args(self): self.assertIn('bar', out.getvalue()) def test_subparser_invalid_option(self): - msg = "Error: invalid choice: 'test' (choose from 'foo')" + msg = "invalid choice: 'test' (choose from 'foo')" with self.assertRaisesMessage(CommandError, msg): management.call_command('subparser', 'test', 12) if PY37: