n8henrie / pycookiecheat

Borrow cookies from your browser's authenticated session for use in Python scripts.
https://n8henrie.com/2013/11/use-chromes-cookies-for-easier-downloading-with-python-requests/
MIT License
744 stars 111 forks source link

browser = Slack now gives "TypeError: key_material must be bytes-like" #54

Closed hraftery closed 10 months ago

hraftery commented 1 year ago

My Issue

The addition I made (adding "Slack" to the list of support browsers) has stopped working, on macOS at least. The error seems mysterious:

>>> cookies = pycookiecheat.chrome_cookies("http://slack.com", browser="Slack")
Traceback (most recent call last):
  File "/opt/homebrew/lib/python3.11/site-packages/cryptography/utils.py", line 34, in _check_byteslike
    memoryview(value)
TypeError: memoryview: a bytes-like object is required, not 'NoneType'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/homebrew/lib/python3.11/site-packages/pycookiecheat/pycookiecheat.py", line 249, in chrome_cookies
    enc_key = kdf.derive(config["my_pass"])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py", line 55, in derive
    utils._check_byteslike("key_material", key_material)
  File "/opt/homebrew/lib/python3.11/site-packages/cryptography/utils.py", line 36, in _check_byteslike
    raise TypeError("{} must be bytes-like".format(name))
TypeError: key_material must be bytes-like

WHYT

Turns out the root issue is way back at this line:

"my_pass": keyring.get_password("{} Safe Storage".format(browser), browser)

which seems to quietly (without even prompting for a password) return nothing if the second parameter doesn't have a match. keyring calls the parameters service_name and username but in Keychain Access at least they seem to be called "Name" and "Account".

Anyway, point is the "Account" seems to have changed from "Slack" to "Slack Key". That's it!

So a hacky fix is to change the line to something like:

"my_pass": keyring.get_password("{} Safe Storage".format(browser), "Slack Key" if browser == "Slack" else browser)

but I'll have to think a bit more about actually doing it properly.

n8henrie commented 1 year ago

This could probably use a better test as well. I wonder if there is a way to install Slack in GitHub Actions?

n8henrie commented 1 year ago

@hraftery as I don't use Slack, this is difficult for me to test. Can you make a PR with the proposed changes after you've confirmed that it's working?

n8henrie commented 11 months ago

Bump.

This issue is pending a response and is blocked until I have more info. To keep the issue list groomed, I will often close these stalled issues if they go a prolonged time without a response. In this case, I will give it another week or so.

hraftery commented 10 months ago

Thanks for the bump. I took a post-xmas moment to reload the brain with this issue.

Turns out you no longer get a "TypeError", because it's now caught earlier and presents a far friendly error message: "ValueError: Could not find a password...". But the underlying issue is the same, so I've tidied up my fix and pushed it (PR coming).

I had a look at test coverage and found test_slack_config() already catches this error. The challenge, as you imply, is that the test will never pass unless Slack is installed (and, I would guess, run and logged in at least once).

n8henrie commented 10 months ago

Thank you!