python-jose icon indicating copy to clipboard operation
python-jose copied to clipboard

Vulnerability on dependency (ecdsa), not planned to be fixed

Open Merinorus opened this issue 1 year ago • 14 comments

Hello,

The ecdsa package is a requirement for this project. There is a vulnerability affecting the latest version (0.18.0), but the maintainers don't plan to fix it. More information here: https://github.com/advisories/GHSA-wj6h-64fc-37mp

Merinorus avatar Jan 24 '24 16:01 Merinorus

I was also brought here by security alerts this morning.

From the python-ecdsa security policy, which the maintainers cite in their reply:

This library was not designed with security in mind. If you are processing data that needs to be protected we suggest you use a quality wrapper around OpenSSL.

So I would ask, what is it being used for in this project?

Edit: It seems this repository is abandoned (#332). The solution is to get away from python-jose as a dependency. My team's requirements are met by PyJWT which is 4x more popular (by stars) but has 5x fewer open issues.

syntaxaire avatar Jan 24 '24 16:01 syntaxaire

So I would ask, what is it being used for in this project?

This project allow you to use multiple backends, one of them is cryptography, as is the solution suggested solution.

It’s all there, in the README: https://github.com/mpdavis/python-jose?tab=readme-ov-file#cryptographic-backends

In other words, ensure you’re using the cryptography backend. You can also uninstall the ecdsa library, even though it’s unused when using the cryptography backend.

EDIT: As more CVEs are uncovered and this project is stale, I've migrated to PyJWT.

JonasKs avatar Jan 30 '24 15:01 JonasKs

guess it makes more sense to just migrate to https://github.com/jpadilla/pyjwt

lsmith77 avatar Feb 02 '24 17:02 lsmith77

hello,

The dependence on this library on ecdsa exposes us to several attacks :

ecdsa Missing Encryption of Sensitive Data [CVSS 7.4] and also ecdsa Timing Attack [CVE-2024-23342]

The ECDSA is not maintained and not built for production: https://github.com/tlsfuzzer/python-ecdsa

Why you are still using it, can you please dispose of it?

I think if you continue to use them you also need to add the following note to your project:

" NOTE: This library should not be used in production settings, see Security for more details."

please help the world to be a safer

yaronbenezra avatar Feb 15 '24 06:02 yaronbenezra

@yaronbenezra , did you even read my reply?

JonasKs avatar Feb 15 '24 07:02 JonasKs

Perhaps a stupid question: If it works with other backends, why not removing ecdsa backend?

mathieuruellanmyscript avatar Feb 15 '24 12:02 mathieuruellanmyscript

The package is not maintained, so no changes can be done to it.

lsmith77 avatar Feb 15 '24 19:02 lsmith77

Anyone know how to replace jose's jwk.construct when using PyJWT?

I documented other migration steps at https://github.com/jpadilla/pyjwt/issues/942

jpmckinney avatar Mar 27 '24 15:03 jpmckinney

For information, I was using JWE only from this lib in an internal project and we ended up using jwcrypto.

Classical scenario: Alice encrypts the message with Bob's public key. Bob decodes the message with his private key.

With python-jose (deprecated):

from jose import jwe

private_key = """
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQBV9L9/gRDGoQuDq3XJyPTIBcRzQ00EppTeb+tHVLv7veX8gy16
KwI0gSbUI/YMABeKGPYlf+RF8n4GQTKjH8cVcITu8LYwnAVZ4ZflQyFO0SFs49Mm
JpZFp41j5YWvqmeREwoq+YHAJkHLiqkx0WEgHFyxNTy8Z4hljqj4vvVDzuECWh7T
5Y3OV4AtrDVM7H/74Bb7MCVgMCsfG1MjwoERQRXXBVgue3pOG3RyE1M05itwS8E3
+iDHr3ny/1T2+wF6e6ZKJAGZ6eQjQrnY7VAlPcsd21HRkrmFx+tKSMcQTTzc9YfL
fXkUVBGUALI5NQujE7jRCxyCdY8eK6JUA1QHAgMBAAECggEAG5ACxAkH7xl/Drax
a4YT7/vhdbB0BvS/seAjitkB+oR3NhR+Rbl62Ik9gTMS1+BDrBW7AGVVNpS+kpTf
fu1WsmpFRjVLxqSRFrQ/N9Xh3Vs0I62ebJJdB3Ll5M2Zo625zgxT61ncoFfkKzeI
b6AbS+esVWqj0ipE04P+bN0W2qohsDQKBfxxOTOzh8t/3waZRqGdP4GGe/dAnv7d
wn0ViUooH3Rh9X4shFBPUV5Gc1qmVfnsUHzvIJb7qsmjaDmJYcGkX0XsJvcraqqD
/qffTMMkuM2AtqX/SWdTMAeyodrsJ/eAMzHKLDePAvQYYJ9DoVbvlbjjZpop68Zn
5qsKEQKBgQCdjYdn6TOzor8xl2xMLgnLhI9pqW9m+eKgPXqSszAx5LLZerwX7hpk
sHtA7fvzzUYH7q/CzmsYiS3dlu4pp9XOorArCKsVlFIXGJ4bhRMyXBBi5srkIDEq
cC+55DehWLsF6MDZofS67AaqMlPfB34es1ctZFrJefpny7yhh9K2CQKBgQCLqnNa
UqLamdpleG2lI9NdSl2gspOPyUI37sEDFPdq7oedtbTV23z36R5MnUanAGh7474Z
ZvLkEfGq9MlIOvkUvPuDPGB0rak3WprjrSJFAOEVFlp2iPcqAd1g1Ihf3braWXPj
t4/EaBbjOjePJnaEdU2COCScLcAbtqlI4FO9jwKBgHSvMd5yZxkeak13IPzWh+iT
l4cgtmHkpcQZZCMr1IDPKOpKrO1oKWHzFoWC+7uXhssvKjqzl7uHNVHMizyMkZvE
/4YPmG2V+KokUEx/ZTVB29zzosYLVX5hsecRr2WuimyY8eL8wHyDe3gnZ9hg+zYP
inwSu+5FiX+/80cKibLJAoGBAIrjUhr8Gl7wqLJHdCHI4qPfFAR+ESfnqCYfE2mR
LAn2cn5u+AnDXx7Zf/wIWv4v9bdd3uk760bKYVz0WEWv/4qT9DmpjPH60E/vlh/b
SDz+htaFiChgRApOGGv2bjeHNA127zwAisNyD3CfsCh2w10tmYppcl6tUGE+4FFM
Y3oZAoGAI8p5HYbwygap9mc5csmBOcfZleZ6iXQcCOtaEYuCbbjMaWjJPvhyp5ys
aiG3uDhxdbYZSrTd92SnZVgfWWRlucE92u4TB4Recsd1JA8pqZvRLMZk80/TPZav
NcMs3qu0kEe40/zpFUAwNPRWr36gmjqJyliXpsDlGxzJ4N9KM3w=
-----END RSA PRIVATE KEY-----
"""

public_key = """
-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBV9L9/gRDGoQuDq3XJyPTI
BcRzQ00EppTeb+tHVLv7veX8gy16KwI0gSbUI/YMABeKGPYlf+RF8n4GQTKjH8cV
cITu8LYwnAVZ4ZflQyFO0SFs49MmJpZFp41j5YWvqmeREwoq+YHAJkHLiqkx0WEg
HFyxNTy8Z4hljqj4vvVDzuECWh7T5Y3OV4AtrDVM7H/74Bb7MCVgMCsfG1MjwoER
QRXXBVgue3pOG3RyE1M05itwS8E3+iDHr3ny/1T2+wF6e6ZKJAGZ6eQjQrnY7VAl
Pcsd21HRkrmFx+tKSMcQTTzc9YfLfXkUVBGUALI5NQujE7jRCxyCdY8eK6JUA1QH
AgMBAAE=
-----END PUBLIC KEY-----
"""

payload = "Hello World"

# Encrypt with public key
encrypted_payload = jwe.encrypt(
        payload, public_key, algorithm="RSA-OAEP-256", encryption="A256GCM"
    )
print(f"encrypted_payload: {encrypted_payload.decode('utf-8')}")

# Decrypt with private key
decoded_payload = jwe.decrypt(encrypted_payload, key=private_key)
print(f"decoded payload: {decoded_payload.decode('utf-8')}")

With jwcrypto:

from jwcrypto import jwe, jwk
from jwcrypto.common import json_encode

private_key = """
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQBV9L9/gRDGoQuDq3XJyPTIBcRzQ00EppTeb+tHVLv7veX8gy16
KwI0gSbUI/YMABeKGPYlf+RF8n4GQTKjH8cVcITu8LYwnAVZ4ZflQyFO0SFs49Mm
JpZFp41j5YWvqmeREwoq+YHAJkHLiqkx0WEgHFyxNTy8Z4hljqj4vvVDzuECWh7T
5Y3OV4AtrDVM7H/74Bb7MCVgMCsfG1MjwoERQRXXBVgue3pOG3RyE1M05itwS8E3
+iDHr3ny/1T2+wF6e6ZKJAGZ6eQjQrnY7VAlPcsd21HRkrmFx+tKSMcQTTzc9YfL
fXkUVBGUALI5NQujE7jRCxyCdY8eK6JUA1QHAgMBAAECggEAG5ACxAkH7xl/Drax
a4YT7/vhdbB0BvS/seAjitkB+oR3NhR+Rbl62Ik9gTMS1+BDrBW7AGVVNpS+kpTf
fu1WsmpFRjVLxqSRFrQ/N9Xh3Vs0I62ebJJdB3Ll5M2Zo625zgxT61ncoFfkKzeI
b6AbS+esVWqj0ipE04P+bN0W2qohsDQKBfxxOTOzh8t/3waZRqGdP4GGe/dAnv7d
wn0ViUooH3Rh9X4shFBPUV5Gc1qmVfnsUHzvIJb7qsmjaDmJYcGkX0XsJvcraqqD
/qffTMMkuM2AtqX/SWdTMAeyodrsJ/eAMzHKLDePAvQYYJ9DoVbvlbjjZpop68Zn
5qsKEQKBgQCdjYdn6TOzor8xl2xMLgnLhI9pqW9m+eKgPXqSszAx5LLZerwX7hpk
sHtA7fvzzUYH7q/CzmsYiS3dlu4pp9XOorArCKsVlFIXGJ4bhRMyXBBi5srkIDEq
cC+55DehWLsF6MDZofS67AaqMlPfB34es1ctZFrJefpny7yhh9K2CQKBgQCLqnNa
UqLamdpleG2lI9NdSl2gspOPyUI37sEDFPdq7oedtbTV23z36R5MnUanAGh7474Z
ZvLkEfGq9MlIOvkUvPuDPGB0rak3WprjrSJFAOEVFlp2iPcqAd1g1Ihf3braWXPj
t4/EaBbjOjePJnaEdU2COCScLcAbtqlI4FO9jwKBgHSvMd5yZxkeak13IPzWh+iT
l4cgtmHkpcQZZCMr1IDPKOpKrO1oKWHzFoWC+7uXhssvKjqzl7uHNVHMizyMkZvE
/4YPmG2V+KokUEx/ZTVB29zzosYLVX5hsecRr2WuimyY8eL8wHyDe3gnZ9hg+zYP
inwSu+5FiX+/80cKibLJAoGBAIrjUhr8Gl7wqLJHdCHI4qPfFAR+ESfnqCYfE2mR
LAn2cn5u+AnDXx7Zf/wIWv4v9bdd3uk760bKYVz0WEWv/4qT9DmpjPH60E/vlh/b
SDz+htaFiChgRApOGGv2bjeHNA127zwAisNyD3CfsCh2w10tmYppcl6tUGE+4FFM
Y3oZAoGAI8p5HYbwygap9mc5csmBOcfZleZ6iXQcCOtaEYuCbbjMaWjJPvhyp5ys
aiG3uDhxdbYZSrTd92SnZVgfWWRlucE92u4TB4Recsd1JA8pqZvRLMZk80/TPZav
NcMs3qu0kEe40/zpFUAwNPRWr36gmjqJyliXpsDlGxzJ4N9KM3w=
-----END RSA PRIVATE KEY-----
"""

public_key = """
-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBV9L9/gRDGoQuDq3XJyPTI
BcRzQ00EppTeb+tHVLv7veX8gy16KwI0gSbUI/YMABeKGPYlf+RF8n4GQTKjH8cV
cITu8LYwnAVZ4ZflQyFO0SFs49MmJpZFp41j5YWvqmeREwoq+YHAJkHLiqkx0WEg
HFyxNTy8Z4hljqj4vvVDzuECWh7T5Y3OV4AtrDVM7H/74Bb7MCVgMCsfG1MjwoER
QRXXBVgue3pOG3RyE1M05itwS8E3+iDHr3ny/1T2+wF6e6ZKJAGZ6eQjQrnY7VAl
Pcsd21HRkrmFx+tKSMcQTTzc9YfLfXkUVBGUALI5NQujE7jRCxyCdY8eK6JUA1QH
AgMBAAE=
-----END PUBLIC KEY-----
"""

payload = "Hello World"

# Encrypt with public key
my_jwe = jwe.JWE(payload.encode("utf-8"), json_encode({"alg": "RSA-OAEP-256", "enc": "A256GCM"}))
jwk_key = jwk.JWK.from_pem(public_key.encode())
my_jwe.add_recipient(jwk_key)
encrypted_payload = my_jwe.serialize(compact=True)
print(f"encrypted_payload: {encrypted_payload}")

# Decrypt with private key
jwk_key = jwk.JWK.from_pem(private_key.encode("utf-8"))
jwe_token = jwe.JWE()
jwe_token.deserialize(encrypted_payload, key=jwk_key)
decoded_payload = jwe_token.payload.decode('utf-8')
print(f"decoded payload: {decoded_payload}")

Merinorus avatar Jun 24 '24 12:06 Merinorus

Is there any desire from the community to fork this project? I see a similar issue with the alternatives in that there isn't a strong community backing and feel as if we'll be back in the same situation sooner rather than later swapping one out for the other.

jamescrowley321 avatar Jul 09 '24 01:07 jamescrowley321

pyjwt (see my earlier comment) is much bigger than python-jose

https://pypistats.org/packages/pyjwt https://pypistats.org/packages/python-jose

jwcrypto is smallest: https://pypistats.org/packages/jwcrypto

Anyway, no need to fork - just use pyjwt.

jpmckinney avatar Jul 09 '24 04:07 jpmckinney

Everyone makes the assumption that pyjwt has a 1:1 to API and that enterprise grade software can just up and switch large implementations. It's likely less work for some of the community to fork and maintain than to switch to another library.

jamescrowley321 avatar Aug 24 '24 14:08 jamescrowley321

Less work for who? Your enterprise? Sounds to me that you want a "community" to do the work for you, unpaid.

"Enterprise grade software" developers should most certainly be able to get rid of a dependency or maintain a fork. There's many suggestions for alternatives in this issue, and in the other issues created the last 12 months.

This library has multiple CVEs, is not maintained, and you should've migrated ages ago.

JonasKs avatar Aug 25 '24 10:08 JonasKs

@JonasKs I wasn't suggesting that. I was going to fork it myself, but no need as you and other have clearly pointed out. Pride before the fall...

The main change is adopting a few types that were not required before, i.e. passing in an instance of PyJWK and an alg to decode instead of a dictionary for the key.

jamescrowley321 avatar Aug 25 '24 19:08 jamescrowley321