Opened 67 minutes ago
#37421 assigned Bug
File-based session backend doesn't enforce integer set_expiry()
| Reported by: | Patel Namraa | Owned by: | Patel Namraa |
|---|---|---|---|
| Component: | contrib.sessions | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Patel Namraa | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
The file-based session backend does not correctly enforce server-side expiration when SessionBase.set_expiry() is called with a positive integer.
In django/contrib/sessions/backends/file.py, FileSession._expiry_date() currently returns the raw _session_expiry value when it is set:
`python
return session_data.get("_session_expiry") or (
self._last_modification() + timedelta(seconds=self.get_session_cookie_age())
)
`
When set_expiry() is given an integer, for example:
`python
session.set_expiry(1)
`
the stored _session_expiry value is 1. _expiry_date() therefore returns 1 rather than calculating an absolute expiration date.
load() subsequently passes this value to get_expiry_age(expiry=1), which returns 1. Since this remains greater than zero, the session is not considered expired even after the configured period of inactivity has elapsed.
The documentation specifies that an integer passed to set_expiry() represents the number of seconds of inactivity before the session expires.
### Steps to reproduce
With the file-based session backend configured:
`python
session = SessionStore()
sessionx = 1
session.set_expiry(1)
session.save()
time.sleep(2.5)
SessionStore(session.session_key).items()
`
The session data is still available after the configured one-second expiry period.
Similarly, the expired session file is not removed by:
`bash
python manage.py clearsessions
`
### Expected behavior
A session configured with set_expiry(seconds) should expire server-side after the specified period of inactivity, and clearsessions should remove the expired session file.
### Actual behavior
For the file-based backend, a positive integer passed to set_expiry() is treated as a constant positive expiry age rather than being converted into an absolute expiration time.
As a result, the session remains valid server-side beyond its configured lifetime, and the corresponding file may remain on disk.
### Proposed fix
Reuse the base session backend's existing expiry-date calculation:
`python
def _expiry_date(self, session_data):
return self.get_expiry_date(
modification=self._last_modification(),
expiry=session_data.get("_session_expiry"),
)
`
This correctly handles integer expiries relative to the file's last modification time while preserving the existing behavior for other expiry formats.
### Tests
I added regression tests covering:
test_expired_integer_expirytest_clearsessions_integer_expiry
Both tests fail with the current implementation and pass with the proposed fix.
The full sessions_tests suite passes with the fix.
Related tickets:
- #18194 — File-based session never expire
- #18458 — related session expiry semantics
- #22938 — related
clearsessionsbehavior for file-based sessions
I would like to work on this issue and submit a patch with the regression tests and fix.