From 140ce8109b3014806ae877ee309b88d7ec729ae6 Mon Sep 17 00:00:00 2001 From: Vincent Ardisson Date: Tue, 30 Jun 2020 18:24:40 +0200 Subject: [PATCH] weboob.browser.browsers: no pickling when saving cookie jar in StatesMixin pickle may be unsafe for loading data. All we want is a cookie jar, we can just serialize its cookies, not necessarily the whole jar with its type and policy. Old format is base64(compress(pickle(jar))). New format is base64(compress(json(jar))) where JSON conversion is on the list of cookies (taking name, value, domain, path, secure (https) and expires). dump_state will now save using the new format while load_state supports both new and old format. This allows compatibility for some time, then later old format support in load_state will be dropped too. --- weboob/browser/browsers.py | 40 +++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/weboob/browser/browsers.py b/weboob/browser/browsers.py index 894765d3cb..a7fba4820c 100644 --- a/weboob/browser/browsers.py +++ b/weboob/browser/browsers.py @@ -1016,16 +1016,34 @@ def locate_browser(self, state): except (requests.exceptions.HTTPError, requests.exceptions.TooManyRedirects): pass + def _load_cookies(self, cookie_state): + try: + uncompressed = zlib.decompress(base64.b64decode(cookie_state)) + except (TypeError, zlib.error, EOFError, ValueError): + self.logger.error('Unable to uncompress cookies from storage') + return + + try: + jcookies = json.loads(uncompressed) + except ValueError: + try: + self.session.cookies = pickle.loads(uncompressed) + except (TypeError, EOFError, ValueError): + self.logger.error('Unable to reload cookies from storage') + else: + self.logger.warning('Reloaded deprecated cookie format') + else: + for jcookie in jcookies: + self.session.cookies.set(**jcookie) + self.logger.info('Reloaded cookies from storage') + def load_state(self, state): if state.get('expire') and parser.parse(state['expire']) < datetime.now(): return self.logger.info('State expired, not reloading it from storage') + if 'cookies' in state: - try: - self.session.cookies = pickle.loads(zlib.decompress(base64.b64decode(state['cookies']))) - except (TypeError, zlib.error, EOFError, ValueError): - self.logger.error('Unable to reload cookies from storage') - else: - self.logger.info('Reloaded cookies from storage') + self._load_cookies(state['cookies']) + for attrname in self.__states__: if attrname in state: setattr(self, attrname, state[attrname]) @@ -1040,7 +1058,15 @@ def dump_state(self): state = {} if hasattr(self, 'page') and self.page: state['url'] = self.page.url - state['cookies'] = base64.b64encode(zlib.compress(pickle.dumps(self.session.cookies, -1))).decode('ascii') + + cookies = [ + { + attr: getattr(cookie, attr) + for attr in ('name', 'value', 'domain', 'path', 'secure', 'expires') + } + for cookie in self.session.cookies + ] + state['cookies'] = base64.b64encode(zlib.compress(json.dumps(cookies).encode('utf-8'))).decode('ascii') for attrname in self.__states__: try: state[attrname] = getattr(self, attrname) -- GitLab