New submission from Karthikeyan Singaravelan <tir.kar...@gmail.com>:

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("https://example.com";)

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

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("https://example.com";)
policy1 = DefaultCookiePolicy()
print(policy1.return_ok(cookie, req))

# Output

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


[0] 
https://github.com/python/cpython/blob/a6e190e94b47324f14e22a09200c68b722d55699/Lib/http/cookiejar.py#L1128

----------
components: Library (Lib)
messages: 345327
nosy: martin.panter, orsenthil, serhiy.storchaka, xtreak
priority: normal
severity: normal
status: open
title: http.cookiejar.DefaultCookiePolicy should use current timestamp instead 
of last updated timestamp value for checking expiry
type: behavior
versions: Python 3.9

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue37246>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to