Title: http.cookiejar.DefaultCookiePolicy should use current timestamp instead of last updated timestamp value for checking expiry
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.9
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: martin.panter, orsenthil, serhiy.storchaka, xtreak
Priority: normal Keywords: patch

Created on 2019-06-12 11:59 by xtreak, last changed 2019-07-30 14:43 by nsiregar.

Pull Requests
URL Status Linked Edit
PR 15023 open nsiregar, 2019-07-30 14:43
Messages (1)
msg345327 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-06-12 11:59
In http.cookiejar module's DefaultCookiePolicy checking for cookie expiry uses the last updated value for _now [0] which is in three actions below. So if the cookies are extracted using the policy and the policy is used for expiry check later it could give incorrect values for expiry check. Like in below example I create a cookie with 1 second from now as expiry date. Sleeping for 1 second and using the same policy causing is_expired to work correctly but return_ok uses self._now with the older value returning the cookie. I propose using time.time() and update self._now or to change cookie.is_expired(self._now) to cookie.is_expired() where is_expired uses time.time() internally

I think it's better to use the current time while using return_ok to compare the cookie expiry. One another error is that self._now is set only when one of the methods is called so evaluating a new policy against a cookie with expiry causes AttributeError since self._now is not yet set.

Actions where self._now is updated

* add_cookie_header
* extract_cookies
* set_cookie_if_ok

import time
from http.cookiejar import CookieJar, DefaultCookiePolicy, time2netscape
from test.test_http_cookiejar import FakeResponse
from urllib.request import Request

delay = 1
now = time.time() + delay
future = time2netscape(now)

req = Request("")

headers = [f"Set-Cookie: a=b; expires={future};"]
res = FakeResponse(headers, "")

policy = DefaultCookiePolicy()
jar = CookieJar(policy=policy)
jar.extract_cookies(res, req)
cookie = jar.make_cookies(res, req)[0]

print(f"{cookie.expires = }")
print(f"{policy.return_ok(cookie, req) = }")

time.sleep(delay + 1)

# Check for cookie expiry where is_expired() returns true
print(f"Current time : {int(time.time())}")
print(f"{cookie.is_expired() = }") # is_expired uses current timestamp so it returns True
print(f"{policy.return_ok(cookie, req) = }") # Return now uses older timestamp and still returns the cookie as valid cookie

# Output

cookie.expires = 1560339939
policy.return_ok(cookie, req) = True
Current time : 1560339940
cookie.is_expired() = True
policy.return_ok(cookie, req) = True

# Using above cookie variable against a new policy would throw AttributeError since self._now is not yet set

req = Request("")
policy1 = DefaultCookiePolicy()
print(policy1.return_ok(cookie, req))

# Output

Traceback (most recent call last):
  File "/tmp/", line 31, in <module>
    print(policy1.return_ok(cookie, req))
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/http/", line 1096, in return_ok
    if not fn(cookie, request):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/http/", line 1128, in return_ok_expires
    if cookie.is_expired(self._now):
AttributeError: 'DefaultCookiePolicy' object has no attribute '_now'

Date User Action Args
2019-07-30 14:43:51nsiregarsetkeywords: + patch
stage: patch review
pull_requests: + pull_request14784
2019-06-12 11:59:44xtreakcreate