actor cookie respects expire_after

Refs GHSA-53fc-rhfg-h7qp

Co-authored-by: Alex Garcia <15178711+asg017@users.noreply.github.com>
This commit is contained in:
Simon Willison 2026-09-03 14:35:48 -07:00
commit f8e8e65af7
2 changed files with 23 additions and 1 deletions

View file

@ -2462,7 +2462,7 @@ class Datasette:
):
data = {"a": actor}
if expire_after:
expires_at = int(time.time()) + (24 * 60 * 60)
expires_at = int(time.time()) + expire_after
data["e"] = baseconv.base62.encode(expires_at)
response.set_cookie("ds_actor", self.sign(data, "actor"))

View file

@ -524,3 +524,25 @@ async def test_root_without_root_enabled_no_special_permissions(ds_client):
)
is not True
), "Root without root_enabled should not automatically get set-column-type"
@pytest.mark.parametrize("expire_after", (1, 300, 3600, 30 * 24 * 60 * 60))
def test_set_actor_cookie_honours_expire_after(expire_after):
# GHSA-53fc-rhfg-h7qp issue 4: expire_after is documented as a number of
# seconds, but every value was being replaced with 24 hours.
from datasette.app import Datasette
from datasette.utils.asgi import Response
ds = Datasette(memory=True)
response = Response.text("")
before = int(time.time())
ds.set_actor_cookie(response, {"id": "test"}, expire_after=expire_after)
after = int(time.time())
(header,) = response._set_cookie_headers
assert header.startswith("ds_actor=")
value = header[len("ds_actor=") :].split(";", 1)[0]
data = ds.unsign(value, "actor")
assert data["a"] == {"id": "test"}
expires_at = baseconv.base62.decode(data["e"])
assert before + expire_after <= expires_at <= after + expire_after