Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Unreleased

- Drop support for Python 3.8 and 3.9.
- Remove previously deprecated code.
- ``Serializer.loads`` no longer accepts arbitrary keyword arguments.
Passing ``max_age`` (or other unexpected kwargs) to a non-timed
serializer now raises ``TypeError`` instead of being silently ignored.
:issue:`429`


Version 2.2.0
Expand Down
9 changes: 6 additions & 3 deletions src/itsdangerous/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,14 @@ def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> N
"""
f.write(self.dumps(obj, salt))

def loads(
self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any
) -> t.Any:
def loads(self, s: str | bytes, salt: str | bytes | None = None) -> t.Any:
"""Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the
signature validation fails.

.. versionchanged:: 2.3
Removed unused ``**kwargs``. Passing unexpected keyword
arguments such as ``max_age`` (only valid on timed serializers)
now raises :exc:`TypeError` instead of being silently ignored.
"""
s = want_bytes(s)
last_exception = None
Expand Down
17 changes: 17 additions & 0 deletions tests/test_itsdangerous/test_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ def value(self):
def test_serializer(self, serializer: Serializer, value: Any):
assert serializer.loads(serializer.dumps(value)) == value

def test_loads_rejects_unexpected_kwargs(
self, serializer: Serializer, value: Any
) -> None:
"""Non-timed serializers must not silently ignore max_age.

Accidentally swapping URLSafeTimedSerializer for URLSafeSerializer
while still passing max_age would otherwise accept expired tokens.
"""
import inspect

if "max_age" in inspect.signature(type(serializer).loads).parameters:
pytest.skip("timed serializer accepts max_age")

signed = serializer.dumps(value)
with pytest.raises(TypeError, match="unexpected keyword argument"):
serializer.loads(signed, max_age=-1) # type: ignore[call-arg]

@pytest.mark.parametrize(
"transform",
(
Expand Down
Loading